# app/controllers/auth_controller.py
from fastapi import FastAPI, UploadFile, File, Form, HTTPException, Depends, Request
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from .. import models, utils, auth
import os
from urllib.parse import urljoin
from app.models import User, BlacklistedToken, Student
from app.database import get_db


def get_full_url(path: str, request: Request):
    if not path:
        return None
    return urljoin(str(request.base_url), f"profiles/{path.lstrip('/')}")

# Send Student Login TO Send OTP
def send_otp_logic(mobile: str, db: Session):
    otp = utils.generate_otp()
    otp_record = db.query(models.OTP).filter(models.OTP.mobile == mobile).first()

    if otp_record:
        otp_record.otp = otp
        otp_record.created_at = datetime.utcnow()
    else:
        db.add(models.OTP(mobile=mobile, otp=otp))

    db.commit()
    utils.send_otp(mobile, otp)
    return {"phone": mobile, "otp": otp}

# Student Login Verify And Send JWT Token
def verify_otp_logic(mobile: str, otp: str, request: Request, db: Session):

    otp_record = db.query(models.OTP).filter(models.OTP.mobile == mobile).first()

    if not otp_record or otp_record.otp != otp:
        raise HTTPException(status_code=400, detail="Invalid OTP")

    if datetime.utcnow() > otp_record.created_at + timedelta(minutes=5):
        raise HTTPException(status_code=400, detail="OTP expired")

    user = db.query(models.User).filter(models.User.mobile == mobile).first()

    if not user:
        user = models.User(mobile=mobile)
        db.add(user)
        db.commit()
        db.refresh(user)

    #Remove OTP record after verification
    db.delete(otp_record)
    db.commit()

    user_type_map = {
        1: "Student",
        2: "Parent"
    }

    gender_map = {
        1: "Male",
        2: "Female"
    }

    # Default values
    profile_picture = None
    gender = None
    dob = None
    location = None
    school_address = None

    if user.user_type == 1 and user.student:
        profile_picture = get_full_url(user.student.profile_picture, request)
        gender = gender_map.get(user.student.gender, "Unknown")
        dob = user.student.dob
        location = user.student.location
        school_address = user.student.school_address

    # elif user.user_type == 2 and user.parent:
    #     profile_picture = get_full_url(user.parent.profile_picture, request)
    #     gender = gender_map.get(user.parent.gender, "Unknown")
    #     dob = user.parent.dob
    #     location = user.parent.location
    #     school_address = user.parent.address

    token = auth.create_access_token({"sub": user.mobile})

    return {
        "status": 200,
        "message": "OTP verified & Login successfully",
        "token": token,
        "token_type": "bearer",
        "user":
            {
                "id": user.id,
                "student_id": user.student_id,
                "parent_id": user.parent_id,
                "name": user.name,
                "gender": gender,
                "mobile": user.mobile,
                "email": user.email,
                "user_type": user.user_type,
                "status_id": user.status_id,
                "profile_picture": profile_picture,
                "created_at": user.created_at,
                "updated_at": user.updated_at,
            }
     }

# Student Upload Profile Picture
def save_profile_picture(file: UploadFile) -> str:
    try:
        UPLOAD_DIR = "app/profiles"  # Adjust as needed
        if not os.path.exists(UPLOAD_DIR):
            os.makedirs(UPLOAD_DIR)

        filename = f"{int(datetime.utcnow().timestamp())}_{file.filename}"
        file_path = os.path.join(UPLOAD_DIR, filename)

        with open(file_path, "wb") as f:
            f.write(file.file.read())

        return file_path  # You can make it relative if storing only 'profiles/filename.jpg'

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to save image: {str(e)}")

# Student Register Functionality
def student_register(
    name: str,
    gender: int,
    email: str,
    mobile: str,
    dob: str,
    location: str,
    school_address: str,
    profile_picture: UploadFile,
    db: Session
):
    try:
        # Save profile image
        profile_picture_path = save_profile_picture(profile_picture)

        # Save student
        new_student = models.Student(
            name=name,
            gender=gender,
            email=email,
            mobile=mobile,
            dob=dob,
            location=location,
            school_address=school_address,
            profile_picture=profile_picture_path,
            created_at=datetime.utcnow(),
            updated_at=datetime.utcnow(),
        )
        db.add(new_student)
        db.commit()
        db.refresh(new_student)

        # Create user linked to student
        new_user = models.User(
            student_id=new_student.id,
            name=name,
            email=email,
            mobile=mobile,
            user_type=1,
            status_id=1,
            created_at=datetime.utcnow(),
            updated_at=datetime.utcnow(),
        )
        db.add(new_user)
        db.commit()
        db.refresh(new_user)

        return {
            "student_id": new_student.id,
            "user_id": new_user.id,
            "profile_picture": profile_picture_path,
            "message": "Student registered successfully"
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# Student Register Send OTP

def verify_otp(mobile: str, otp: str, db: Session):

    otp_record = db.query(models.OTP).filter(models.OTP.mobile == mobile).first()

    if not otp_record or otp_record.otp != otp:
        raise HTTPException(status_code=400, detail="Invalid OTP")

    if datetime.utcnow() > otp_record.created_at + timedelta(minutes=5):
        raise HTTPException(status_code=400, detail="OTP expired")

    # Remove OTP record after verification
    db.delete(otp_record)
    db.commit()

    return {"verified": True}

# Get User Info
def get_user_info(current_user: User, db: Session, request: Request):
    try:
        result = (
            db.query(
                User,
                Student.profile_picture,
                Student.dob,
                Student.location,
                Student.school_address,
                Student.gender,
            )
            .join(Student, Student.id == User.student_id)
            .filter(User.id == current_user.id)
            .first()
        )

        if not result:
            raise HTTPException(status_code=404, detail="User not found")

        user, profile_picture, dob, location, school_address, gender = result

        user_type_map = {
            1: "Student",
            2: "Parent"
        }

        gender_map = {
            1: "Male",
            2: "Female"
        }

        user_info = {

            "id": user.id,
            "name": user.name,
            "mobile": user.mobile,
            "email": user.email,
            "user_type": user_type_map.get(user.user_type, "Unknown"),
            "status_id": user.status_id,
            "image": get_full_url(profile_picture, request),
            "dob": dob,
            "location": location,
            "school_address": school_address,
            "gender": gender_map.get(gender, "Unknown")
        }

        return {
            "status": True,
            "user_info": user_info
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# Logout Functionality
def logout(request: Request, db: Session = Depends(get_db)):
    auth_header = request.headers.get("Authorization")
    if not auth_header or not auth_header.startswith("Bearer "):
        raise HTTPException(status_code=401, detail="Authorization header missing")

    token = auth_header.split(" ")[1]

    # ✅ Add token to blacklist
    existing = db.query(models.BlacklistedToken).filter(models.BlacklistedToken.token == token).first()
    if existing:
        return {"status": True, "message": "Already logged out"}

    blacklisted_token = models.BlacklistedToken(token=token)
    db.add(blacklisted_token)
    db.commit()

    return {"status": True, "message": "Logged out successfully"}
