from flask import Flask, request, jsonify, make_response
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_restful import Resource, Api
from flasgger import Swagger, swag_from

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///auth_api.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SWAGGER'] = {'title': 'Auth API', 'uiversion': 3}
swagger = Swagger(app)

db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
api = Api(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password = db.Column(db.String(120), nullable=False)

    def __repr__(self):
        return f'<User {self.username}>'

db.create_all()

class Register(Resource):
    @swag_from({
        'tags': ['Authentication'],
        'definitions': {'User': {'type': 'object', 'properties': {'username': {'type': 'string'}, 'password': {'type': 'string'}}}},
        'responses': {'201': {'description': 'User registered successfully'}, '400': {'description': 'Missing username or password'}},
        'parameters': [{'in': 'body', 'name': 'body', 'description': 'User object that needs to be registered', 'required': True, 'schema': {'$ref': '#/definitions/User'}}]
    })
    def post(self):
        data = request.get_json()
        username = data.get('username')
        password = data.get('password')

        if not username or not password:
            return {"message": "Missing username or password"}, 400

        hashed_password = bcrypt.generate_password_hash(password).decode('utf-8')

        new_user = User(username=username, password=hashed_password)
        db.session.add(new_user)
        db.session.commit()

        return {"message": "User registered successfully"}, 201


class Login(Resource):
    @swag_from({
        'tags': ['Authentication'],
        'definitions': {'User': {'type': 'object', 'properties': {'username': {'type': 'string'}, 'password': {'type': 'string'}}}},
        'responses': {'200': {'description': 'Logged in successfully'}, '401': {'description': 'Invalid username or password'}},
        'parameters': [{'in': 'body', 'name': 'body', 'description': 'User object that needs to log in', 'required': True, 'schema': {'$ref': '#/definitions/User'}}]
    })
    def post(self):
        data = request.get_json()
        username = data.get('username')
        password = data.get('password')

        user = User.query.filter_by(username=username).first()
        if user and bcrypt.check_password_hash(user.password, password):
            return {"message": "Logged in successfully", "user_id": user.id}, 200
        else:
            return {"message": "Invalid username or password"}, 401

class Secret(Resource):
    @swag_from({
        'tags': ['Protected Resource'],
        'responses': {'200': {'description': 'Welcome to the secret resource!'}, '401': {'description': 'Unauthorized'}},
        'parameters': [{'in': 'header', 'name': 'Authorization', 'type': 'string', 'required': True}]
    })
    def get(self):
        auth_header = request.headers.get('Authorization')
        if not auth_header:
            return {"message": "Missing Authorization header"}, 401

        user_id = auth_header.split(" ")[0]
        user = User.query.get(user_id)

        if user:
            return {"message": "Welcome to the secret resource!"}, 200
        else:
            return {"message": "Unauthorized"}, 401

api.add_resource(Register, '/register')
api.add_resource(Login, '/login')
api.add_resource(Secret, '/secret')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5200)
