package handlers

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	"furry-sos-backend/config"
)

// ============================================================
// REVIEW TABLE
// ============================================================

func createVolunteerReviewsTable() {
	query := `
		CREATE TABLE IF NOT EXISTS volunteer_reviews (
			review_id BIGINT PRIMARY KEY AUTO_INCREMENT,

			assignment_id INT NOT NULL,

			user_id INT NOT NULL,

			volunteer_id INT NOT NULL,

			rating INT NOT NULL,

			comment TEXT,

			created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

			updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
				ON UPDATE CURRENT_TIMESTAMP,

			UNIQUE KEY uq_review_assignment_user
			(
				assignment_id,
				user_id
			)
		)
	`

	if _, err := config.DB.Exec(query); err != nil {
		fmt.Println(
			"❌ CREATE volunteer_reviews ERROR:",
			err,
		)
	}
}

// ============================================================
// COMMON JSON RESPONSE
// ============================================================

func reviewJSON(
	w http.ResponseWriter,
	status int,
	data map[string]interface{},
) {
	w.Header().Set(
		"Content-Type",
		"application/json; charset=utf-8",
	)

	w.WriteHeader(status)

	_ = json.NewEncoder(w).Encode(data)
}

// ============================================================
// GET USER ID
// ============================================================

func getReviewUserID(r *http.Request) (int, error) {

	userIDStr := strings.TrimSpace(
		r.Header.Get("X-User-ID"),
	)

	if userIDStr == "" {
		userIDStr = strings.TrimSpace(
			r.URL.Query().Get("user_id"),
		)
	}

	if userIDStr == "" {
		return 0, fmt.Errorf(
			"ไม่พบ user_id",
		)
	}

	userID, err := strconv.Atoi(
		userIDStr,
	)

	if err != nil || userID <= 0 {
		return 0, fmt.Errorf(
			"user_id ไม่ถูกต้อง",
		)
	}

	return userID, nil
}

// ============================================================
// GET ASSIGNMENT INFORMATION
//
// ตรวจทั้ง emergency_reports และ deceased_reports
//
// return:
// reportID
// volunteerID
// userID
// status
// reportType
// ============================================================

func getAssignmentInfo(
	reportID int,
) (
	int,
	int,
	int,
	string,
	string,
	error,
) {

	// ========================================================
	// EMERGENCY
	// ========================================================

	var (
		volunteerID int
		userID      int
		status      string
	)

	err := config.DB.QueryRow(
		`
		SELECT
			user_id,
			COALESCE(assigned_volunteer_id, 0),
			status
		FROM emergency_reports
		WHERE report_id = ?
		LIMIT 1
		`,
		reportID,
	).Scan(
		&userID,
		&volunteerID,
		&status,
	)

	if err == nil {

		return reportID, volunteerID, userID, status, "emergency", nil
	}

	if err != sql.ErrNoRows {

		return 0, 0, 0, "", "", err
	}

	// ========================================================
	// DECEASED
	// ========================================================

	err = config.DB.QueryRow(
		`
		SELECT
			user_id,
			COALESCE(assigned_volunteer_id, 0),
			status
		FROM deceased_reports
		WHERE report_id = ?
		LIMIT 1
		`,
		reportID,
	).Scan(
		&userID,
		&volunteerID,
		&status,
	)

	if err != nil {

		if err == sql.ErrNoRows {

			return 0, 0, 0, "", "", fmt.Errorf("ไม่พบเคส %d", reportID)
		}

		return 0, 0, 0, "", "", err
	}

	return reportID, volunteerID, userID, status, "deceased", nil
}

// ============================================================
// CHECK REVIEW STATUS
//
// GET /api/review/check?report_id=110
//
// 🌟 แก้ไข: อนุญาตให้รีวิวเฉพาะเมื่อ "เสร็จสิ้น" เท่านั้น
// ============================================================

func CheckReviewStatus(
	w http.ResponseWriter,
	r *http.Request,
) {

	if r.Method != http.MethodGet {

		reviewJSON(
			w,
			http.StatusMethodNotAllowed,
			map[string]interface{}{
				"success": false,
				"message": "Method not allowed",
			},
		)

		return
	}

	// ========================================================
	// REPORT ID
	// ========================================================

	reportIDStr := strings.TrimSpace(
		r.URL.Query().Get("report_id"),
	)

	if reportIDStr == "" {

		reviewJSON(
			w,
			http.StatusBadRequest,
			map[string]interface{}{
				"success": false,
				"message": "ไม่พบ report_id",
			},
		)

		return
	}

	reportID, err := strconv.Atoi(
		reportIDStr,
	)

	if err != nil || reportID <= 0 {

		reviewJSON(
			w,
			http.StatusBadRequest,
			map[string]interface{}{
				"success": false,
				"message": "report_id ไม่ถูกต้อง",
			},
		)

		return
	}

	// ========================================================
	// USER ID
	// ========================================================

	userID, err := getReviewUserID(r)

	if err != nil {

		reviewJSON(
			w,
			http.StatusUnauthorized,
			map[string]interface{}{
				"success": false,
				"message": err.Error(),
			},
		)

		return
	}

	// ========================================================
	// ASSIGNMENT
	// ========================================================

	reportID,
		volunteerID,
		reportOwnerID,
		status,
		reportType,
		err := getAssignmentInfo(reportID)

	if err != nil {

		fmt.Println(
			"❌ CHECK REVIEW ASSIGNMENT ERROR:",
			err,
		)

		reviewJSON(
			w,
			http.StatusNotFound,
			map[string]interface{}{
				"success":     false,
				"can_review":  false,
				"is_reviewed": false,
				"message":     err.Error(),
			},
		)

		return
	}

	// ========================================================
	// USER ต้องเป็นเจ้าของเคส
	// ========================================================

	if reportOwnerID != userID {

		reviewJSON(
			w,
			http.StatusForbidden,
			map[string]interface{}{
				"success":     false,
				"can_review":  false,
				"is_reviewed": false,
				"message":     "คุณไม่มีสิทธิ์รีวิวเคสนี้",
			},
		)

		return
	}

	// ========================================================
	// ยังไม่มีอาสาสมัคร
	// ========================================================

	if volunteerID <= 0 {

		reviewJSON(
			w,
			http.StatusOK,
			map[string]interface{}{
				"success":      true,
				"can_review":   false,
				"is_reviewed":  false,
				"volunteer_id": 0,
				"status":       status,
				"report_type":  reportType,
				"message":      "ยังไม่มีอาสาสมัครรับเคส",
			},
		)

		return
	}

	// ========================================================
	// CREATE TABLE
	// ========================================================

	createVolunteerReviewsTable()

	// ========================================================
	// CHECK EXISTING REVIEW
	// ========================================================

	var reviewID int

	err = config.DB.QueryRow(
		`
		SELECT review_id
		FROM volunteer_reviews
		WHERE assignment_id = ?
		AND user_id = ?
		LIMIT 1
		`,
		reportID,
		userID,
	).Scan(
		&reviewID,
	)

	if err == nil {

		reviewJSON(
			w,
			http.StatusOK,
			map[string]interface{}{
				"success":      true,
				"can_review":   false,
				"is_reviewed":  true,
				"review_id":    reviewID,
				"volunteer_id": volunteerID,
				"status":       status,
				"report_type":  reportType,
			},
		)

		return
	}

	if err != sql.ErrNoRows {

		reviewJSON(
			w,
			http.StatusInternalServerError,
			map[string]interface{}{
				"success": false,
				"message": "ตรวจสอบรีวิวไม่สำเร็จ: " + err.Error(),
			},
		)

		return
	}

	// ========================================================
	// 🌟 REVIEW
	//
	// อนุญาตให้รีวิวเฉพาะเมื่อ "เสร็จสิ้น" เท่านั้น
	// เปลี่ยนจาก assigned → เหลือแค่ completed
	// ========================================================

	reviewableStatuses := map[string]bool{
		"completed": true, // ✅ เคสฉุกเฉินที่เสร็จสิ้น
		"collected": true, // ✅ เคสซากสัตว์ที่เก็บกู้แล้ว
	}

	normalizedStatus := strings.ToLower(
		strings.TrimSpace(status),
	)

	if !reviewableStatuses[normalizedStatus] {

		reviewJSON(
			w,
			http.StatusOK,
			map[string]interface{}{
				"success":      true,
				"can_review":   false,
				"is_reviewed":  false,
				"volunteer_id": volunteerID,
				"status":       status,
				"report_type":  reportType,
				"message":      "เคสยังไม่เสร็จสิ้น ไม่สามารถรีวิวได้",
			},
		)

		return
	}

	// ========================================================
	// เสร็จสิ้น + ยังไม่เคยรีวิว
	// ========================================================

	reviewJSON(
		w,
		http.StatusOK,
		map[string]interface{}{
			"success":      true,
			"can_review":   true,
			"is_reviewed":  false,
			"review_id":    0,
			"volunteer_id": volunteerID,
			"status":       status,
			"report_type":  reportType,
			"message":      "สามารถรีวิวอาสาสมัครได้",
		},
	)

	return
}

// ============================================================
// SUBMIT REVIEW
//
// POST /api/review/submit
//
// 🌟 แก้ไข: อนุญาตให้ส่งรีวิวเฉพาะเมื่อ "เสร็จสิ้น" เท่านั้น
// ============================================================

func SubmitReview(
	w http.ResponseWriter,
	r *http.Request,
) {

	if r.Method != http.MethodPost {

		reviewJSON(
			w,
			http.StatusMethodNotAllowed,
			map[string]interface{}{
				"success": false,
				"message": "Method not allowed",
			},
		)

		return
	}

	// ========================================================
	// USER ID
	// ========================================================

	userID, err := getReviewUserID(r)

	if err != nil {

		reviewJSON(
			w,
			http.StatusUnauthorized,
			map[string]interface{}{
				"success": false,
				"message": err.Error(),
			},
		)

		return
	}

	// ========================================================
	// REQUEST
	// ========================================================

	var body struct {
		UserID int `json:"user_id"`

		VolunteerID int `json:"volunteer_id"`

		AssignmentID int `json:"assignment_id"`

		Rating int `json:"rating"`

		Comment string `json:"comment"`
	}

	if err := json.NewDecoder(
		r.Body,
	).Decode(&body); err != nil {

		reviewJSON(
			w,
			http.StatusBadRequest,
			map[string]interface{}{
				"success": false,
				"message": "JSON ไม่ถูกต้อง",
			},
		)

		return
	}

	// ========================================================
	// ใช้ User ID จาก Header เป็นหลัก
	// ========================================================

	body.UserID = userID

	// ========================================================
	// VALIDATION
	// ========================================================

	if body.AssignmentID <= 0 {

		reviewJSON(
			w,
			http.StatusBadRequest,
			map[string]interface{}{
				"success": false,
				"message": "ไม่พบ assignment_id",
			},
		)

		return
	}

	if body.VolunteerID <= 0 {

		reviewJSON(
			w,
			http.StatusBadRequest,
			map[string]interface{}{
				"success": false,
				"message": "ไม่พบ volunteer_id",
			},
		)

		return
	}

	if body.Rating < 1 ||
		body.Rating > 5 {

		reviewJSON(
			w,
			http.StatusBadRequest,
			map[string]interface{}{
				"success": false,
				"message": "คะแนนต้องอยู่ระหว่าง 1 ถึง 5",
			},
		)

		return
	}

	// ========================================================
	// GET ASSIGNMENT
	// ========================================================

	reportID,
		assignedVolunteerID,
		reportOwnerID,
		status,
		reportType,
		err := getAssignmentInfo(body.AssignmentID)

	if err != nil {

		reviewJSON(
			w,
			http.StatusNotFound,
			map[string]interface{}{
				"success": false,
				"message": err.Error(),
			},
		)

		return
	}

	// ========================================================
	// SECURITY
	// ========================================================

	if reportOwnerID != userID {

		reviewJSON(
			w,
			http.StatusForbidden,
			map[string]interface{}{
				"success": false,
				"message": "คุณไม่มีสิทธิ์รีวิวเคสนี้",
			},
		)

		return
	}

	if assignedVolunteerID != body.VolunteerID {

		reviewJSON(
			w,
			http.StatusBadRequest,
			map[string]interface{}{
				"success": false,
				"message": "อาสาสมัครไม่ตรงกับเคส",
			},
		)

		return
	}

	// ========================================================
	// 🌟 ตรวจสถานะ — อนุญาตเฉพาะ "เสร็จสิ้น" เท่านั้น
	// ========================================================

	normalizedStatus := strings.ToLower(strings.TrimSpace(status))

	reviewableStatuses := map[string]bool{
		"completed": true, // ✅ เคสฉุกเฉินที่เสร็จสิ้น
		"collected": true, // ✅ เคสซากสัตว์ที่เก็บกู้แล้ว
	}

	if !reviewableStatuses[normalizedStatus] {

		reviewJSON(
			w,
			http.StatusConflict,
			map[string]interface{}{
				"success": false,
				"message": "เคสนี้ยังไม่เสร็จสิ้น ไม่สามารถรีวิวได้",
				"status":  status,
			},
		)

		return
	}

	// ========================================================
	// CREATE TABLE
	// ========================================================

	createVolunteerReviewsTable()

	// ========================================================
	// CHECK DUPLICATE
	// ========================================================

	var existingReviewID int

	err = config.DB.QueryRow(
		`
		SELECT review_id
		FROM volunteer_reviews
		WHERE assignment_id = ?
		AND user_id = ?
		LIMIT 1
		`,
		reportID,
		userID,
	).Scan(
		&existingReviewID,
	)

	if err == nil {

		reviewJSON(
			w,
			http.StatusConflict,
			map[string]interface{}{
				"success":     false,
				"is_reviewed": true,
				"review_id":   existingReviewID,
				"message":     "คุณรีวิวเคสนี้ไปแล้ว",
			},
		)

		return
	}

	if err != sql.ErrNoRows {

		reviewJSON(
			w,
			http.StatusInternalServerError,
			map[string]interface{}{
				"success": false,
				"message": "ตรวจสอบรีวิวซ้ำไม่สำเร็จ: " + err.Error(),
			},
		)

		return
	}

	// ========================================================
	// INSERT
	// ========================================================

	result, err := config.DB.Exec(
		`
		INSERT INTO volunteer_reviews
		(
			assignment_id,
			user_id,
			volunteer_id,
			rating,
			comment,
			created_at,
			updated_at
		)
		VALUES
		(
			?,
			?,
			?,
			?,
			?,
			NOW(),
			NOW()
		)
		`,
		reportID,
		userID,
		body.VolunteerID,
		body.Rating,
		strings.TrimSpace(
			body.Comment,
		),
	)

	if err != nil {

		reviewJSON(
			w,
			http.StatusInternalServerError,
			map[string]interface{}{
				"success": false,
				"message": "บันทึกรีวิวไม่สำเร็จ: " + err.Error(),
			},
		)

		return
	}

	reviewID, err := result.LastInsertId()

	if err != nil {

		reviewID = 0
	}

	// ========================================================
	// RESPONSE
	// ========================================================

	reviewJSON(
		w,
		http.StatusOK,
		map[string]interface{}{
			"success":       true,
			"message":       "✅ ส่งรีวิวสำเร็จ!",
			"review_id":     reviewID,
			"assignment_id": reportID,
			"volunteer_id":  body.VolunteerID,
			"rating":        body.Rating,
			"comment": strings.TrimSpace(
				body.Comment,
			),
			"report_type": reportType,
		},
	)
}

// ============================================================
// GET REVIEW BY ASSIGNMENT
//
// GET /api/review/get?assignment_id=110
// ============================================================

func GetReviewByAssignment(
	w http.ResponseWriter,
	r *http.Request,
) {

	if r.Method != http.MethodGet {

		reviewJSON(
			w,
			http.StatusMethodNotAllowed,
			map[string]interface{}{
				"success": false,
				"message": "Method not allowed",
			},
		)

		return
	}

	assignmentIDStr :=
		strings.TrimSpace(
			r.URL.Query().Get(
				"assignment_id",
			),
		)

	if assignmentIDStr == "" {

		assignmentIDStr =
			strings.TrimSpace(
				r.URL.Query().Get(
					"report_id",
				),
			)
	}

	assignmentID, err :=
		strconv.Atoi(
			assignmentIDStr,
		)

	if err != nil ||
		assignmentID <= 0 {

		reviewJSON(
			w,
			http.StatusBadRequest,
			map[string]interface{}{
				"success": false,
				"message": "assignment_id ไม่ถูกต้อง",
			},
		)

		return
	}

	userID, err := getReviewUserID(r)

	if err != nil {

		reviewJSON(
			w,
			http.StatusUnauthorized,
			map[string]interface{}{
				"success": false,
				"message": err.Error(),
			},
		)

		return
	}

	createVolunteerReviewsTable()

	var (
		reviewID    int
		volunteerID int
		rating      int
		comment     string
		createdAt   time.Time
	)

	err = config.DB.QueryRow(
		`
		SELECT
			review_id,
			volunteer_id,
			rating,
			COALESCE(comment, ''),
			created_at
		FROM volunteer_reviews
		WHERE assignment_id = ?
		AND user_id = ?
		LIMIT 1
		`,
		assignmentID,
		userID,
	).Scan(
		&reviewID,
		&volunteerID,
		&rating,
		&comment,
		&createdAt,
	)

	if err == sql.ErrNoRows {

		reviewJSON(
			w,
			http.StatusNotFound,
			map[string]interface{}{
				"success":     false,
				"message":     "ยังไม่พบรีวิว",
				"is_reviewed": false,
			},
		)

		return
	}

	if err != nil {

		reviewJSON(
			w,
			http.StatusInternalServerError,
			map[string]interface{}{
				"success": false,
				"message": "โหลดรีวิวไม่สำเร็จ: " + err.Error(),
			},
		)

		return
	}

	reviewJSON(
		w,
		http.StatusOK,
		map[string]interface{}{
			"success":     true,
			"is_reviewed": true,
			"review": map[string]interface{}{
				"review_id":     reviewID,
				"assignment_id": assignmentID,
				"user_id":       userID,
				"volunteer_id":  volunteerID,
				"rating":        rating,
				"comment":       comment,
				"created_at":    createdAt,
			},
		},
	)
}