from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from typing import Optional
from datetime import date

from database import get_connection
from crm_notifications import create_crm_notification


router = APIRouter(
    prefix="/performance",
    tags=["Performance"]
)


# =========================================================
# MODELS
# =========================================================

class FinalReviewRequest(BaseModel):
    employee_id: str
    task_id: int
    submission_id: int
    rating: float
    manager_feedback: Optional[str] = ""
    given_by: Optional[str] = None


# =========================================================
# POINT CALCULATION
# =========================================================

def calculate_points(rating: float) -> int:

    rating = float(rating)

    if rating >= 5:
        return 20

    if rating >= 4:
        return 16

    if rating >= 3:
        return 12

    if rating >= 2:
        return 8

    if rating >= 1:
        return 4

    return 0


# =========================================================
# FINAL REVIEW
#
# ONLY THIS API CREATES PERFORMANCE POINTS
# =========================================================

@router.post("/final-review")
def final_review(payload: FinalReviewRequest):

    conn = get_connection()

    try:

        cursor = conn.cursor(dictionary=True)

        # -------------------------------------------------
        # VALIDATE RATING
        # -------------------------------------------------

        if payload.rating < 1 or payload.rating > 5:

            raise HTTPException(
                status_code=400,
                detail="Rating must be between 1 and 5."
            )

        # -------------------------------------------------
        # GET SUBMISSION
        # -------------------------------------------------

        cursor.execute(
            """
            SELECT
                id,
                task_id,
                employee_id,
                progress,
                status
            FROM task_submissions
            WHERE id = %s
            """,
            (payload.submission_id,)
        )

        submission = cursor.fetchone()

        if not submission:

            raise HTTPException(
                status_code=404,
                detail="Submission not found."
            )

        # -------------------------------------------------
        # VALIDATE TASK
        # -------------------------------------------------

        if int(submission["task_id"]) != int(payload.task_id):

            raise HTTPException(
                status_code=400,
                detail="Submission does not belong to this task."
            )

        # -------------------------------------------------
        # VALIDATE EMPLOYEE
        # -------------------------------------------------

        if str(submission["employee_id"]) != str(
            payload.employee_id
        ):

            raise HTTPException(
                status_code=400,
                detail="Submission does not belong to this employee."
            )

        # -------------------------------------------------
        # VALIDATE PROGRESS
        # -------------------------------------------------

        progress = float(
            submission["progress"] or 0
        )

        if progress < 100:

            raise HTTPException(
                status_code=400,
                detail=(
                    f"Final review allowed only at 100% progress. "
                    f"Current progress: {progress}%"
                )
            )

        # -------------------------------------------------
        # CALCULATE POINTS
        # -------------------------------------------------

        points = calculate_points(
            payload.rating
        )

        # -------------------------------------------------
        # UPDATE FINAL SUBMISSION
        # -------------------------------------------------

        cursor.execute(
            """
            UPDATE task_submissions
            SET
                task_rating = %s,
                manager_feedback = %s,
                status = 'Completed'
            WHERE id = %s
            """,
            (
                payload.rating,
                payload.manager_feedback or "",
                payload.submission_id
            )
        )

        # -------------------------------------------------
        # CHECK EXISTING PERFORMANCE RECORD
        #
        # UNIQUE submission_id prevents duplicates.
        # -------------------------------------------------

        cursor.execute(
            """
            SELECT id
            FROM performance_records
            WHERE submission_id = %s
            LIMIT 1
            """,
            (payload.submission_id,)
        )

        existing = cursor.fetchone()

        # -------------------------------------------------
        # UPDATE EXISTING
        # -------------------------------------------------

        if existing:

            cursor.execute(
                """
                UPDATE performance_records
                SET
                    employee_id = %s,
                    task_id = %s,
                    rating = %s,
                    points = %s,
                    manager_feedback = %s,
                    given_by = %s,
                    performance_date = %s
                WHERE submission_id = %s
                """,
                (
                    payload.employee_id,
                    payload.task_id,
                    payload.rating,
                    points,
                    payload.manager_feedback or "",
                    payload.given_by,
                    date.today(),
                    payload.submission_id
                )
            )

            record_id = existing["id"]

        # -------------------------------------------------
        # INSERT NEW
        # -------------------------------------------------

        else:

            cursor.execute(
                """
                INSERT INTO performance_records
                (
                    employee_id,
                    task_id,
                    submission_id,
                    rating,
                    points,
                    manager_feedback,
                    given_by,
                    performance_date
                )
                VALUES
                (
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s
                )
                """,
                (
                    payload.employee_id,
                    payload.task_id,
                    payload.submission_id,
                    payload.rating,
                    points,
                    payload.manager_feedback or "",
                    payload.given_by,
                    date.today()
                )
            )

            record_id = cursor.lastrowid

        conn.commit()
        try:

            create_crm_notification(
                employee_id=payload.employee_id,
                title="Performance Review Updated",
                message=(
                    f"Your task performance has been reviewed. "
                    f"Rating: {payload.rating}/5, "
                    f"Points: {points}"
                ),
                notification_type="performance"
            )

        except Exception as notification_error:

            print(
                "PERFORMANCE CRM NOTIFICATION ERROR:",
                str(notification_error)
            )

        return {
            "success": True,
            "message": "Final performance review saved successfully.",
            "record_id": record_id,
            "employee_id": payload.employee_id,
            "task_id": payload.task_id,
            "submission_id": payload.submission_id,
            "rating": payload.rating,
            "points": points
        }

    except HTTPException:
        conn.rollback()
        raise

    except Exception as e:

        conn.rollback()

        print(
            "FINAL PERFORMANCE ERROR:",
            str(e)
        )

        raise HTTPException(
            status_code=500,
            detail=str(e)
        )

    finally:

        try:
            cursor.close()
        except:
            pass

        try:
            conn.close()
        except:
            pass


# =========================================================
# MY PERFORMANCE
#
# Employee apni performance dekhega.
# =========================================================

@router.get("/employee/{employee_id}")
def get_employee_performance(
    employee_id: str
):

    conn = get_connection()

    try:

        cursor = conn.cursor(dictionary=True)

        cursor.execute(
            """
            SELECT
                pr.id,
                pr.employee_id,
                pr.task_id,
                pr.submission_id,
                pr.rating,
                pr.points,
                pr.manager_feedback,
                pr.given_by,
                pr.performance_date,
                pr.created_at,

                t.title AS task_title

            FROM performance_records pr

            LEFT JOIN tasks t
                ON t.id = pr.task_id

            WHERE pr.employee_id = %s

            ORDER BY
                pr.performance_date DESC,
                pr.created_at DESC
            """,
            (employee_id,)
        )

        records = cursor.fetchall()

        return {
            "success": True,
            "employee_id": employee_id,
            "records": records
        }

    finally:

        cursor.close()
        conn.close()


# =========================================================
# MY PERFORMANCE SUMMARY
# =========================================================

@router.get("/employee/{employee_id}/summary")
def get_employee_performance_summary(
    employee_id: str
):

    conn = get_connection()

    try:

        cursor = conn.cursor(dictionary=True)

        cursor.execute(
            """
            SELECT

                COUNT(*) AS total_tasks,

                COALESCE(
                    SUM(points),
                    0
                ) AS total_points,

                COALESCE(
                    ROUND(
                        AVG(rating),
                        2
                    ),
                    0
                ) AS average_rating

            FROM performance_records

            WHERE employee_id = %s
            """,
            (employee_id,)
        )

        summary = cursor.fetchone()

        return {
            "success": True,
            "employee_id": employee_id,
            "total_tasks": int(
                summary["total_tasks"] or 0
            ),
            "total_points": int(
                summary["total_points"] or 0
            ),
            "average_rating": float(
                summary["average_rating"] or 0
            )
        }

    finally:

        cursor.close()
        conn.close()


# =========================================================
# ALL EMPLOYEES PERFORMANCE
#
# Manager / HR ke liye
# =========================================================

@router.get("/all")
def get_all_performance():

    conn = get_connection()

    try:

        cursor = conn.cursor(dictionary=True)

        cursor.execute(
            """
            SELECT

                employee_id,

                COUNT(*) AS total_tasks,

                COALESCE(
                    SUM(points),
                    0
                ) AS total_points,

                COALESCE(
                    ROUND(
                        AVG(rating),
                        2
                    ),
                    0
                ) AS average_rating

            FROM performance_records

            GROUP BY employee_id

            ORDER BY
                total_points DESC
            """
        )

        records = cursor.fetchall()

        return {
            "success": True,
            "records": records
        }

    finally:

        cursor.close()
        conn.close()


# =========================================================
# PARTICULAR EMPLOYEE DETAIL
#
# Manager / HR employee ki complete history dekhe
# =========================================================

@router.get("/employee/{employee_id}/detail")
def get_employee_performance_detail(
    employee_id: str
):

    conn = get_connection()

    try:

        cursor = conn.cursor(dictionary=True)

        # -------------------------------------------------
        # SUMMARY
        # -------------------------------------------------

        cursor.execute(
            """
            SELECT

                COUNT(*) AS total_tasks,

                COALESCE(
                    SUM(points),
                    0
                ) AS total_points,

                COALESCE(
                    ROUND(
                        AVG(rating),
                        2
                    ),
                    0
                ) AS average_rating,

                COALESCE(
                    MAX(points),
                    0
                ) AS highest_points

            FROM performance_records

            WHERE employee_id = %s
            """,
            (employee_id,)
        )

        summary = cursor.fetchone()

        # -------------------------------------------------
        # HISTORY
        # -------------------------------------------------

        cursor.execute(
            """
            SELECT

                pr.id,
                pr.employee_id,
                pr.task_id,
                pr.submission_id,
                pr.rating,
                pr.points,
                pr.manager_feedback,
                pr.given_by,
                pr.performance_date,
                pr.created_at,

                t.title AS task_title

            FROM performance_records pr

            LEFT JOIN tasks t
                ON t.id = pr.task_id

            WHERE pr.employee_id = %s

            ORDER BY
                pr.performance_date DESC,
                pr.created_at DESC
            """,
            (employee_id,)
        )

        history = cursor.fetchall()

        return {
            "success": True,
            "employee_id": employee_id,

            "summary": {
                "total_tasks": int(
                    summary["total_tasks"] or 0
                ),
                "total_points": int(
                    summary["total_points"] or 0
                ),
                "average_rating": float(
                    summary["average_rating"] or 0
                ),
                "highest_points": int(
                    summary["highest_points"] or 0
                )
            },

            "history": history
        }

    finally:

        cursor.close()
        conn.close()