package handlers

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"furry-sos-backend/config"
)

// ======================================================
// GET VOLUNTEER BODY RETRIEVAL
//
// GET /api/volunteer/body-retrieval
// GET /api/volunteer/body-retrieval?user_id=16
//
// งานประเภท "จัดการซากสัตว์"
// ใช้ข้อมูลจาก deceased_reports เท่านั้น
//
// ไม่ใช้ emergency_reports
// ======================================================

func GetVolunteerBodyRetrieval(
	w http.ResponseWriter,
	r *http.Request,
) {

	if r.Method != http.MethodGet {
		http.Error(
			w,
			"Method not allowed",
			http.StatusMethodNotAllowed,
		)
		return
	}

	userID, err := getUserIDFromRequest(r)

	if err != nil {
		userIDStr := r.URL.Query().Get("user_id")

		if userIDStr == "" {
			http.Error(
				w,
				"ไม่พบ User ID",
				http.StatusUnauthorized,
			)
			return
		}

		userID, err = strconv.Atoi(userIDStr)

		if err != nil {
			http.Error(
				w,
				"User ID ไม่ถูกต้อง",
				http.StatusBadRequest,
			)
			return
		}
	}

	role, err := getUserRole(userID)

	if err != nil {
		http.Error(
			w,
			"ไม่พบข้อมูลผู้ใช้งาน",
			http.StatusNotFound,
		)
		return
	}

	if role != "volunteer" {
		http.Error(
			w,
			"บัญชีนี้ไม่ใช่อาสาสมัคร",
			http.StatusForbidden,
		)
		return
	}

	var (
		workingArea string
		isApproved  bool
	)

	err = config.DB.QueryRow(
		`
		SELECT
			COALESCE(working_area, ''),
			is_approved
		FROM volunteers
		WHERE user_id = ?
		LIMIT 1
		`,
		userID,
	).Scan(
		&workingArea,
		&isApproved,
	)

	if err != nil {
		http.Error(
			w,
			"ไม่พบข้อมูลอาสาสมัคร",
			http.StatusNotFound,
		)
		return
	}

	if !isApproved {
		http.Error(
			w,
			"อาสาสมัครยังไม่ได้รับการอนุมัติ",
			http.StatusForbidden,
		)
		return
	}

	query := `
		SELECT
			report_id,
			animal_type,
			location_lat,
			location_lng,
			location_address,
			image_url,
			notes,
			status,
			assigned_volunteer_id,
			created_at
		FROM deceased_reports
		WHERE status = 'pending'
		AND assigned_volunteer_id IS NULL
		ORDER BY created_at DESC
	`

	rows, err := config.DB.Query(query)

	if err != nil {
		http.Error(
			w,
			"ไม่สามารถโหลดรายการงานได้: "+err.Error(),
			http.StatusInternalServerError,
		)
		return
	}

	defer rows.Close()

	cases := make([]map[string]interface{}, 0)

	for rows.Next() {
		var (
			reportID            int
			animalType          string
			locationLat         float64
			locationLng         float64
			locationAddress     string
			imageURL            string
			notes               string
			status              string
			assignedVolunteerID *int
			createdAt           interface{}
		)

		err := rows.Scan(
			&reportID,
			&animalType,
			&locationLat,
			&locationLng,
			&locationAddress,
			&imageURL,
			&notes,
			&status,
			&assignedVolunteerID,
			&createdAt,
		)

		if err != nil {
			continue
		}

		caseCode := fmt.Sprintf(
			"BR-%04d",
			reportID,
		)

		displayAnimalType := animalType

		if displayAnimalType == "" {
			displayAnimalType = "ไม่ระบุประเภทสัตว์"
		}

		displayNotes := notes

		if displayNotes == "" {
			displayNotes = "ไม่มีรายละเอียดเพิ่มเติม"
		}

		cases = append(
			cases,
			map[string]interface{}{
				"report_id": reportID,

				"case_code": caseCode,

				"animal_type": displayAnimalType,

				"location_lat": locationLat,

				"location_lng": locationLng,

				"location_address": locationAddress,

				"image_url": imageURL,

				"notes": displayNotes,

				"status": status,

				"assigned_volunteer_id": assignedVolunteerID,

				"created_at": createdAt,
			},
		)
	}

	if err := rows.Err(); err != nil {
		http.Error(
			w,
			"เกิดข้อผิดพลาดในการอ่านข้อมูล: "+err.Error(),
			http.StatusInternalServerError,
		)
		return
	}

	w.Header().Set(
		"Content-Type",
		"application/json; charset=utf-8",
	)

	response := map[string]interface{}{
		"success":      true,
		"user_id":      userID,
		"working_area": workingArea,
		"count":        len(cases),
		"cases":        cases,
	}

	json.NewEncoder(w).Encode(response)
}

// ======================================================
// POST VOLUNTEER BODY RETRIEVAL - ACCEPT
//
// POST /api/volunteer/body-retrieval/accept
//
// รับงานจัดการซากสัตว์
// ======================================================

func AcceptVolunteerBodyRetrieval(
	w http.ResponseWriter,
	r *http.Request,
) {

	if r.Method != http.MethodPost {
		http.Error(
			w,
			"Method not allowed",
			http.StatusMethodNotAllowed,
		)
		return
	}

	var body struct {
		UserID   int `json:"user_id"`
		ReportID int `json:"report_id"`
		CaseID   int `json:"case_id"`
	}

	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		http.Error(
			w,
			"ข้อมูล JSON ไม่ถูกต้อง",
			http.StatusBadRequest,
		)
		return
	}

	reportID := body.ReportID

	if reportID == 0 {
		reportID = body.CaseID
	}

	if body.UserID <= 0 || reportID <= 0 {
		http.Error(
			w,
			"ข้อมูล user_id หรือ report_id ไม่ถูกต้อง",
			http.StatusBadRequest,
		)
		return
	}

	role, err := getUserRole(body.UserID)

	if err != nil {
		http.Error(
			w,
			"ไม่พบข้อมูลผู้ใช้งาน",
			http.StatusNotFound,
		)
		return
	}

	if role != "volunteer" {
		http.Error(
			w,
			"บัญชีนี้ไม่ใช่อาสาสมัคร",
			http.StatusForbidden,
		)
		return
	}

	var volunteerID int
	var isApproved bool

	err = config.DB.QueryRow(
		`
		SELECT
			volunteer_id,
			is_approved
		FROM volunteers
		WHERE user_id = ?
		LIMIT 1
		`,
		body.UserID,
	).Scan(
		&volunteerID,
		&isApproved,
	)

	if err != nil {
		http.Error(
			w,
			"ไม่พบข้อมูลอาสาสมัคร",
			http.StatusNotFound,
		)
		return
	}

	if !isApproved {
		http.Error(
			w,
			"อาสาสมัครยังไม่ได้รับการอนุมัติ",
			http.StatusForbidden,
		)
		return
	}

	// ==================================================
	// รับงานแบบป้องกันการรับซ้ำ (Transaction)
	// ==================================================

	tx, err := config.DB.Begin()
	if err != nil {
		http.Error(w, "เริ่ม Transaction ไม่ได้", http.StatusInternalServerError)
		return
	}
	defer tx.Rollback()

	result, err := tx.Exec(
		`
		UPDATE deceased_reports
		SET
			assigned_volunteer_id = ?,
			status = 'assigned',
			updated_at = NOW()
		WHERE report_id = ?
		AND status = 'pending'
		AND assigned_volunteer_id IS NULL
		`,
		volunteerID,
		reportID,
	)

	if err != nil {
		http.Error(
			w,
			"ไม่สามารถรับงานได้: "+err.Error(),
			http.StatusInternalServerError,
		)
		return
	}

	rowsAffected, err := result.RowsAffected()

	if err != nil {
		http.Error(
			w,
			"ไม่สามารถตรวจสอบการรับงานได้",
			http.StatusInternalServerError,
		)
		return
	}

	if rowsAffected == 0 {
		http.Error(
			w,
			"งานนี้ถูกรับไปแล้ว หรือไม่อยู่ในสถานะรอรับงาน",
			http.StatusConflict,
		)
		return
	}

	// ==================================================
	// ✅ ปิด tracking เก่า (ถ้ามี)
	// ==================================================
	tx.Exec(`
		UPDATE case_tracking
		SET is_current = 0
		WHERE report_id = ? AND report_type = 'deceased'
	`, reportID)

	// ==================================================
	// ✅ Insert tracking ใหม่ (accepted)
	// ==================================================
	_, err = tx.Exec(`
		INSERT INTO case_tracking
		(report_id, report_type, status, status_description, status_order, is_current, created_by, created_at)
		VALUES (?, 'deceased', 'accepted', 'รับเคสแล้ว', 1, 1, 'volunteer', NOW())
	`, reportID)

	if err != nil {
		http.Error(
			w,
			"บันทึก tracking ไม่สำเร็จ: "+err.Error(),
			http.StatusInternalServerError,
		)
		return
	}

	// ==================================================
	// 🔔 แจ้งเตือนเจ้าของเคส
	// ==================================================
	var ownerUserID int

	err = tx.QueryRow(
		`
		SELECT user_id
		FROM deceased_reports
		WHERE report_id = ?
		LIMIT 1
		`,
		reportID,
	).Scan(&ownerUserID)

	if err == nil {
		createNotificationsTable()

		tx.Exec(
			`
			INSERT INTO notifications
			(
				user_id,
				title,
				message,
				is_read,
				notification_type,
				reference_id
			)
			VALUES (?, ?, ?, FALSE, 'system', ?)
			`,
			ownerUserID,
			"✅ มีอาสาสมัครรับงานแล้ว",
			fmt.Sprintf(
				"เคส BR-%04d มีอาสาสมัครรับงานแล้ว สามารถติดตามสถานะได้",
				reportID,
			),
			reportID,
		)
	}

	if err := tx.Commit(); err != nil {
		http.Error(w, "commit ไม่สำเร็จ", http.StatusInternalServerError)
		return
	}

	w.Header().Set(
		"Content-Type",
		"application/json; charset=utf-8",
	)

	json.NewEncoder(w).Encode(
		map[string]interface{}{
			"success":      true,
			"message":      "รับงานเรียบร้อยแล้ว",
			"user_id":      body.UserID,
			"volunteer_id": volunteerID,
			"report_id":    reportID,
			"status":       "accepted",
		},
	)
}

// ======================================================
// POST VOLUNTEER BODY RETRIEVAL - COMPLETE
//
// POST /api/volunteer/body-retrieval/complete
//
// รับ multipart/form-data
//
// fields: user_id, report_id, note
// file: completion_image
//
// ✅ แก้: อัปเดต case_tracking ด้วย (สำคัญ!)
// ======================================================

func CompleteVolunteerBodyRetrieval(
	w http.ResponseWriter,
	r *http.Request,
) {

	if r.Method != http.MethodPost {
		http.Error(
			w,
			"Method not allowed",
			http.StatusMethodNotAllowed,
		)
		return
	}

	err := r.ParseMultipartForm(
		20 << 20,
	)

	if err != nil {
		http.Error(
			w,
			"ข้อมูล multipart ไม่ถูกต้อง: "+err.Error(),
			http.StatusBadRequest,
		)
		return
	}

	userID, err := strconv.Atoi(
		r.FormValue("user_id"),
	)

	if err != nil || userID <= 0 {
		http.Error(
			w,
			"user_id ไม่ถูกต้อง",
			http.StatusBadRequest,
		)
		return
	}

	reportID, err := strconv.Atoi(
		r.FormValue("report_id"),
	)

	if err != nil || reportID <= 0 {
		http.Error(
			w,
			"report_id ไม่ถูกต้อง",
			http.StatusBadRequest,
		)
		return
	}

	note := r.FormValue("note")

	role, err := getUserRole(userID)

	if err != nil {
		http.Error(
			w,
			"ไม่พบข้อมูลผู้ใช้งาน",
			http.StatusNotFound,
		)
		return
	}

	if role != "volunteer" {
		http.Error(
			w,
			"บัญชีนี้ไม่ใช่อาสาสมัคร",
			http.StatusForbidden,
		)
		return
	}

	var volunteerID int
	var isApproved bool

	err = config.DB.QueryRow(
		`
		SELECT
			volunteer_id,
			is_approved
		FROM volunteers
		WHERE user_id = ?
		LIMIT 1
		`,
		userID,
	).Scan(
		&volunteerID,
		&isApproved,
	)

	if err != nil {
		http.Error(
			w,
			"ไม่พบข้อมูลอาสาสมัคร",
			http.StatusNotFound,
		)
		return
	}

	if !isApproved {
		http.Error(
			w,
			"อาสาสมัครยังไม่ได้รับการอนุมัติ",
			http.StatusForbidden,
		)
		return
	}

	// ==================================================
	// ตรวจสอบว่ามีรูป
	// ==================================================

	file, header, err := r.FormFile(
		"completion_image",
	)

	if err != nil {
		http.Error(
			w,
			"กรุณาแนบรูปภาพหลังปฏิบัติงาน",
			http.StatusBadRequest,
		)
		return
	}

	defer file.Close()

	// ==================================================
	// ตรวจสอบว่าอาสาคนนี้เป็นผู้รับงานจริง
	// ==================================================

	var assignedVolunteerID *int
	var status string

	err = config.DB.QueryRow(
		`
		SELECT
			assigned_volunteer_id,
			status
		FROM deceased_reports
		WHERE report_id = ?
		LIMIT 1
		`,
		reportID,
	).Scan(
		&assignedVolunteerID,
		&status,
	)

	if err != nil {
		http.Error(
			w,
			"ไม่พบงาน",
			http.StatusNotFound,
		)
		return
	}

	if assignedVolunteerID == nil ||
		*assignedVolunteerID != volunteerID {

		http.Error(
			w,
			"อาสาสมัครคนนี้ไม่ได้รับงานนี้",
			http.StatusForbidden,
		)
		return
	}

	if status != "assigned" &&
		status != "collected" {

		http.Error(
			w,
			"งานนี้ไม่สามารถปิดงานได้ในสถานะปัจจุบัน",
			http.StatusConflict,
		)
		return
	}

	// ==================================================
	// สร้างโฟลเดอร์
	// ==================================================

	uploadDir := "uploads/body-retrieval"

	err = os.MkdirAll(
		uploadDir,
		0755,
	)

	if err != nil {
		http.Error(
			w,
			"สร้างโฟลเดอร์อัปโหลดไม่สำเร็จ",
			http.StatusInternalServerError,
		)
		return
	}

	// ==================================================
	// สร้างชื่อไฟล์
	// ==================================================

	ext := filepath.Ext(
		header.Filename,
	)

	if ext == "" {
		ext = ".jpg"
	}

	filename := fmt.Sprintf(
		"body_retrieval_%d_%d%s",
		reportID,
		time.Now().Unix(),
		ext,
	)

	filePath := filepath.Join(
		uploadDir,
		filename,
	)

	dst, err := os.Create(filePath)

	if err != nil {
		http.Error(
			w,
			"สร้างไฟล์รูปไม่สำเร็จ",
			http.StatusInternalServerError,
		)
		return
	}

	defer dst.Close()

	_, err = io.Copy(
		dst,
		file,
	)

	if err != nil {
		http.Error(
			w,
			"บันทึกรูปภาพไม่สำเร็จ",
			http.StatusInternalServerError,
		)
		return
	}

	imageURL := "/uploads/body-retrieval/" + filename

	// ==================================================
	// ✅ ใช้ Transaction เพื่อให้ทั้ง 3 ตารางอัปเดตพร้อมกัน
	// ==================================================

	tx, err := config.DB.Begin()
	if err != nil {
		http.Error(w, "เริ่ม Transaction ไม่ได้", http.StatusInternalServerError)
		return
	}
	defer tx.Rollback()

	// ---------- 1. อัปเดต deceased_reports ----------
	_, err = tx.Exec(
		`
		UPDATE deceased_reports
		SET
			status = 'completed',
			updated_at = NOW()
		WHERE report_id = ?
		AND assigned_volunteer_id = ?
		`,
		reportID,
		volunteerID,
	)

	if err != nil {
		http.Error(
			w,
			"อัปเดตสถานะงานไม่สำเร็จ: "+err.Error(),
			http.StatusInternalServerError,
		)
		return
	}

	// ---------- 2. ✅ ปิด tracking เก่า ----------
	_, err = tx.Exec(`
		UPDATE case_tracking
		SET is_current = 0
		WHERE report_id = ? AND report_type = 'deceased'
	`, reportID)

	if err != nil {
		http.Error(
			w,
			"ปิด tracking เก่าไม่สำเร็จ: "+err.Error(),
			http.StatusInternalServerError,
		)
		return
	}

	// ---------- 3. ✅ Insert tracking ใหม่ (completed) ----------
	_, err = tx.Exec(`
		INSERT INTO case_tracking
		(report_id, report_type, status, status_description, status_order, is_current, created_by, created_at)
		VALUES (?, 'deceased', 'completed', 'เสร็จสิ้น', 5, 1, 'volunteer', NOW())
	`, reportID)

	if err != nil {
		http.Error(
			w,
			"บันทึก tracking ใหม่ไม่สำเร็จ: "+err.Error(),
			http.StatusInternalServerError,
		)
		return
	}

	// ---------- 4. แจ้งเตือนเจ้าของเคส ----------
	var ownerUserID int

	err = tx.QueryRow(
		`
		SELECT user_id
		FROM deceased_reports
		WHERE report_id = ?
		LIMIT 1
		`,
		reportID,
	).Scan(&ownerUserID)

	if err == nil {
		createNotificationsTable()

		tx.Exec(
			`
			INSERT INTO notifications
			(
				user_id,
				title,
				message,
				is_read,
				notification_type,
				reference_id
			)
			VALUES (?, ?, ?, FALSE, 'system', ?)
			`,
			ownerUserID,
			"🎉 งานจัดการซากสัตว์เสร็จสิ้น",
			fmt.Sprintf(
				"เคส BR-%04d ดำเนินการเสร็จสิ้นแล้ว สามารถตรวจสอบรายละเอียดได้",
				reportID,
			),
			reportID,
		)
	}

	if err := tx.Commit(); err != nil {
		http.Error(w, "commit ไม่สำเร็จ", http.StatusInternalServerError)
		return
	}

	// ==================================================
	// RESPONSE
	// ==================================================

	w.Header().Set(
		"Content-Type",
		"application/json; charset=utf-8",
	)

	json.NewEncoder(w).Encode(
		map[string]interface{}{
			"success":      true,
			"message":      "ส่งงานเรียบร้อยแล้ว",
			"user_id":      userID,
			"volunteer_id": volunteerID,
			"report_id":    reportID,
			"status":       "completed",
			"image_url":    imageURL,
			"note":         note,
		},
	)
}