package main_1

import (
	"database/sql"
	"fmt"
	"log"
	"strings"
	"time"
)

// Employee โครงสร้างข้อมูลพนักงาน
type Employee struct {
	EMP_ID    string
	US_NAME   string
	BARCODE   string
	US_PASSWD string
	TNAME     string
	FNAME     string
	LNAME     string
	NICK      string
	
	// สรุปข้อมูลรายพนักงาน
	TotalCount int
	G1Count    int
	G2Count    int
	G3Count    int
	GNPLCount  int
	TotalPrice float64
	G1Price    float64
	G2Price    float64
	G3Price    float64
	GNPLPrice  float64
}

// Loan3Record โครงสร้างข้อมูลรายงานสินเชื่อ 3
type Loan3Record struct {
	CT_NO           string
	PS_NAME         string
	DUE_AMNT        float64
	NOTPAY_AMNT     float64
	PRICE           float64
	PAYDUE_COUNT    int
	PAYAMNT         float64
	BL_DUE_1        float64
	XSTATUS         string
	LOCK_STATUS     string
	ZONE_CODE       string
	DF_ADDRHOME     string
	DF_TUNAME       string
	DF_AMNAME       string
	DF_PRNAME       string
	STNPY           int
	NOTPAY_COUNT    int
	STNON           int
	NON_COUNT       int
	PRODUCT_ID      string
	PRODUCT_NAME    string
	SERIE_NO        string
	GROUP_NO        string
	TYPE_NO         string
	BRAND_NAME      string
	FML_NAME        string
	OCCUPATION_NAME string
	L_TYPE          string
	UPDATE_Y        string
	UPDATE_M        string
	EMP_NAME        string
}

// GetXStatusText แปลง xstatus เป็นข้อความ
func (r Loan3Record) GetXStatusText() string {
	s := strings.TrimSpace(r.XSTATUS)
	switch s {
	case "0":
		return "ปกติ"
	case "1":
		return "สินค้าขายต่อ"
	case "2":
		return "สินค้าหาย"
	case "3":
		return "สินค้าจำนำ"
	case "4":
		return "สินค้าอยู่ต่างจังหวัด"
	case "5":
		return "สินค้าเกิดอุบัติเหตุ"
	case "6":
		return "สินค้าอยู่ สน."
	case "7":
		return "สินค้าไม่มีข้อมูล(พบซื้อหรือค้ำแต่ไม่พบสินค้า)"
	case "8":
		return "แก๊งค์"
	case "9":
		return "สินค้าไม่มีข้อมูล(ไม่พบซื้อและค้ำและสินค้า)"
	default:
		return s
	}
}

// GetLockStatusText แปลง lock_status เป็นข้อความตามเงื่อนไข
func (r Loan3Record) GetLockStatusText() string {
	c := strings.TrimSpace(r.LOCK_STATUS)
	sumcost := r.BL_DUE_1

	if c == "N" || c == "" {
		return "ปกติ"
	} else if c == "E" {
		return "ผิดปกติ (มีปัญหา)"
	} else if c == "W" {
		return "รับคืนรอไถ่ถอน"
	} else if c == "R" {
		return "รับคืน ปิดสัญญา"
	} else if c == "O" {
		return "รับสินค้าตีเทิร์น ปิดสัญญา"
	} else if c == "C" {
		return "รับคืนสินค้า ปิดสัญญา"
	} else if c == "L" {
		return "หนี้สูญ ปิดสัญญา"
	} else if c == "X" {
		return "สัญญาถูกยกเลิกแล้ว"
	} else if c == "D" || c == "Y" {
		return "ติดต่อสินเชื่อ"
	} else if c == "F" {
		if sumcost <= 0 {
			return "หมดงวด (B/L)"
		} else {
			return "หมดงวด(ค้างค่าเบี้ยปรับและค่าอื่นฯ)"
		}
	}
	return c
}

// FormatMoney ฟอร์แมตตัวเลขให้มีคอมม่าและทศนิยม 2 ตำแหน่ง
func (r Loan3Record) FormatMoney(v float64) string {
	s := fmt.Sprintf("%.2f", v)
	parts := strings.Split(s, ".")
	intPart := parts[0]
	decPart := parts[1]

	var result []string
	length := len(intPart)
	for i, char := range intPart {
		if i > 0 && (length-i)%3 == 0 && intPart[i-1] != '-' {
			result = append(result, ",")
		}
		result = append(result, string(char))
	}

	return strings.Join(result, "") + "." + decPart
}

// GetPaidPercent คำนวณ % ชำระไปแล้ว
func (r Loan3Record) GetPaidPercent() float64 {
	if r.PRICE <= 0 {
		return 0
	}
	return (r.PAYAMNT / r.PRICE) * 100
}

// GetGroupText แปลง L_TYPE เป็นข้อความกลุ่ม
func (r Loan3Record) GetGroupText() string {
	t := strings.TrimSpace(r.L_TYPE)
	switch t {
	case "1":
		return "1-3 งวด"
	case "2":
		return "ค้าง 1-2"
	case "3":
		return "ค้าง >= 3"
	case "NPL":
		return "NPL"
	default:
		return t
	}
}

// LoanPeriod โครงสร้างปีและเดือนที่มีข้อมูล
type LoanPeriod struct {
	Year  string
	Month string
}

// GroupSummary สรุปข้อมูลแยกตามกลุ่ม
type GroupSummary struct {
	TotalCount int
	G1Count    int
	G2Count    int
	G3Count    int
	GNPLCount  int
	TotalPrice float64
	G1Price    float64
	G2Price    float64
	G3Price    float64
	GNPLPrice  float64
}

// FetchLoanEmployees ดึงข้อมูลพนักงานพร้อมสรุปจำนวนรายและมูลค่าตามปีและเดือนที่กำหนด
func FetchLoanEmployees(db *sql.DB, year, month string) []Employee {
	// ถ้าไม่มีปีหรือเดือน ให้หาล่าสุด
	if year == "" || month == "" {
		db.QueryRow(`
			SELECT TOP 1 UPDATE_Y, UPDATE_M 
			FROM CONFIG.dbo.LOAN3_CSV 
			ORDER BY UPDATE_Y DESC, CAST(UPDATE_M AS INT) DESC
		`).Scan(&year, &month)
	}

	query := `
		SELECT 
			e.EMP_ID, e.US_NAME, e.TNAME, e.FNAME, e.LNAME, e.NICK,
			COUNT(c.CT_NO) as TotalCount,
			SUM(CASE WHEN c.L_TYPE = '1' THEN 1 ELSE 0 END) as G1Count,
			SUM(CASE WHEN c.L_TYPE = '2' THEN 1 ELSE 0 END) as G2Count,
			SUM(CASE WHEN c.L_TYPE = '3' THEN 1 ELSE 0 END) as G3Count,
			SUM(CASE WHEN c.L_TYPE = 'NPL' THEN 1 ELSE 0 END) as GNPLCount,
			SUM(ISNULL(h.due_amnt, 0)) as TotalPrice,
			SUM(CASE WHEN c.L_TYPE = '1' THEN ISNULL(h.due_amnt, 0) ELSE 0 END) as G1Price,
			SUM(CASE WHEN c.L_TYPE = '2' THEN ISNULL(h.due_amnt, 0) ELSE 0 END) as G2Price,
			SUM(CASE WHEN c.L_TYPE = '3' THEN ISNULL(h.due_amnt, 0) ELSE 0 END) as G3Price,
			SUM(CASE WHEN c.L_TYPE = 'NPL' THEN ISNULL(h.due_amnt, 0) ELSE 0 END) as GNPLPrice
		FROM EHONGDB.dbo.EMPLOYEE e
		LEFT JOIN CONFIG.dbo.LOAN3_CSV c ON c.US_NAME = e.US_NAME AND c.UPDATE_Y = @p1 AND c.UPDATE_M = @p2
		LEFT JOIN EHONGDB.dbo.hps_ctmain h ON h.ct_no = c.CT_NO
		WHERE e.DP_ID = '09' AND e.EM_STATUS = 'NM'
		GROUP BY e.EMP_ID, e.US_NAME, e.TNAME, e.FNAME, e.LNAME, e.NICK
		ORDER BY e.EMP_ID
	`
	rows, err := db.Query(query, sql.Named("p1", year), sql.Named("p2", month))
	if err != nil {
		log.Println("Error fetching employees with counts:", err)
		return nil
	}
	defer rows.Close()

	var employees []Employee
	for rows.Next() {
		var e Employee
		err := rows.Scan(
			&e.EMP_ID, &e.US_NAME, &e.TNAME, &e.FNAME, &e.LNAME, &e.NICK,
			&e.TotalCount, &e.G1Count, &e.G2Count, &e.G3Count, &e.GNPLCount,
			&e.TotalPrice, &e.G1Price, &e.G2Price, &e.G3Price, &e.GNPLPrice,
		)
		if err == nil {
			employees = append(employees, e)
		}
	}
	return employees
}

// SaveLoanCSV บันทึกข้อมูลจาก CSV ลงฐานข้อมูล CONFIG.dbo.LOAN3_CSV พร้อมข้อมูลผู้ใช้งานและชื่อไฟล์
func SaveLoanCSV(db *sql.DB, records [][]string, userName string, fileName string) error {
	// เริ่ม Transaction เพื่อความปลอดภัย
	tx, err := db.Begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()

	// เตรียม Statement สำหรับ Insert (บันทึกผู้ใช้ที่อัพเดตและชื่อไฟล์)
	stmt, err := tx.Prepare("INSERT INTO CONFIG.dbo.LOAN3_CSV (CT_NO, UPDATE_Y, UPDATE_M, L_TYPE, US_NAME_UPDATE, UPDATE_FILE) VALUES (@p1, @p2, @p3, @p4, @p5, @p6)")
	if err != nil {
		return err
	}
	defer stmt.Close()

	// วนลูปบันทึกข้อมูล (ข้าม Header บรรทัดแรกถ้ามี)
	for i, record := range records {
		if i == 0 {
			continue // Skip header
		}
		if len(record) < 3 {
			continue
		}
		// บันทึกข้อมูลพร้อม userName ของผู้อัพเดต และวันที่ปัจจุบัน (ในคอลัมน์ UPDATE_FILE)
		now := time.Now().Format("2006-01-02 15:04:05")
		lType := ""
		if len(record) >= 4 {
			lType = record[3]
		}
		_, err := stmt.Exec(record[0], record[1], record[2], lType, userName, now)
		if err != nil {
			log.Println("Error inserting CSV row:", err)
			return err
		}
	}

	return tx.Commit()
}

// UpdateLoan3Employee อัพเดตพนักงานและสถานะให้กับรายการสินเชื่อ
func UpdateLoan3Employee(db *sql.DB, year, month, usName string, ctNos []string) error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()

	var query string
	var finalUsName string
	if usName == "UNASSIGNED" {
		query = "UPDATE CONFIG.dbo.LOAN3_CSV SET US_NAME = '', L_STATUS = 0 WHERE UPDATE_Y = @p2 AND UPDATE_M = @p3 AND CT_NO = @p4"
		finalUsName = ""
	} else {
		query = "UPDATE CONFIG.dbo.LOAN3_CSV SET US_NAME = @p1, L_STATUS = 1 WHERE UPDATE_Y = @p2 AND UPDATE_M = @p3 AND CT_NO = @p4"
		finalUsName = usName
	}

	stmt, err := tx.Prepare(query)
	if err != nil {
		return err
	}
	defer stmt.Close()

	for _, ct := range ctNos {
		_, err := stmt.Exec(finalUsName, year, month, ct)
		if err != nil {
			log.Println("Error updating CT_NO:", ct, err)
			return err
		}
	}

	return tx.Commit()
}

// FetchLoan3Report ดึงข้อมูลรายงานจัดสรรสินเชื่อ 3 ตามปีและเดือน
func FetchLoan3Report(db *sql.DB, year, month, assignedUser string) []Loan3Record {
	query := `
		SELECT 
			ISNULL(h.ct_no, ''), ISNULL(h.ps_name, ''), ISNULL(h.due_amnt, 0), 
			ISNULL(h.notpay_amnt, 0), ISNULL(h.price, 0), ISNULL(h.paydue_count, 0), 
			ISNULL(h.payamnt, 0), ISNULL((h.price - h.payamnt), 0) AS bl_due_1,
			ISNULL(h.xstatus, ''), ISNULL(h.lock_status, ''), ISNULL(h.zone_code, ''), 
			ISNULL(h.df_addrhome, ''), ISNULL(h.df_tuname, ''), ISNULL(h.df_amname, ''), 
			ISNULL(h.df_prname, ''),
			ISNULL(h.stnpy, 0), ISNULL(h.notpay_count, 0),
			ISNULL(h.stnon, 0), ISNULL(h.non_count, 0),
			ISNULL(h.PRODUCT_ID, ''), ISNULL(p.PRODUCT_NAME1, ''), 
			ISNULL(p.SERIE_NO, ''), ISNULL(p.GROUP_NO, ''), ISNULL(p.TYPE_NO, ''),
			ISNULL(b.BRAND_NAME, ''), ISNULL(f.FML_NAME, ''),
			ISNULL(o.OC_NAME, ''),
			ISNULL(c.L_TYPE, ''),
			c.UPDATE_Y, c.UPDATE_M,
			ISNULL(e.TNAME, '')  + ' ' + ISNULL(e.FNAME, '') + ' ' + ISNULL(e.LNAME, '') AS emp_name
		FROM EHONGDB.dbo.hps_ctmain h
		INNER JOIN CONFIG.dbo.LOAN3_CSV c ON h.ct_no = c.CT_NO
		LEFT JOIN EHONGDB.dbo.EMPLOYEE e ON e.US_NAME = c.US_NAME
		OUTER APPLY (
			SELECT TOP 1 PRODUCT_NAME1, SERIE_NO, GROUP_NO, TYPE_NO, BRAND_NO, FML_NO
			FROM EHONGDB.dbo.PRODUCT_PRODUCTDATA
			WHERE PRODUCT_ID = h.PRODUCT_ID
		) p
		OUTER APPLY (
			SELECT TOP 1 FML_NAME
			FROM EHONGDB.dbo.product_family
			WHERE BRAND_NO = p.BRAND_NO AND FML_NO = p.FML_NO
		) f
		OUTER APPLY (
			SELECT TOP 1 BRAND_NAME
			FROM EHONGDB.dbo.product_brand
			WHERE BRAND_NO = p.BRAND_NO
		) b
		OUTER APPLY (
			SELECT TOP 1 PS_JOB
			FROM EHONGDB.dbo.PERSON
			WHERE PS_ID = h.ps_id
		) ps
		OUTER APPLY (
			SELECT TOP 1 OC_NAME
			FROM EHONGDB.dbo.OCCUPATION
			WHERE OC_CODE = ps.PS_JOB
		) o
		WHERE c.UPDATE_Y = @p1 AND c.UPDATE_M = @p2
	`
	var args []interface{}
	args = append(args, sql.Named("p1", year), sql.Named("p2", month))

	if assignedUser == "UNASSIGNED" {
		query += " AND (c.US_NAME IS NULL OR c.US_NAME = '')"
	} else if assignedUser == "ASSIGNED_ONLY" {
		query += " AND (c.US_NAME IS NOT NULL AND c.US_NAME != '')"
	} else if assignedUser != "ALL" && assignedUser != "" {
		query += " AND c.US_NAME = @p3"
		args = append(args, sql.Named("p3", assignedUser))
	}

	rows, err := db.Query(query, args...)
	if err != nil {
		log.Println("Error fetching Loan3 report:", err)
		return nil
	}
	defer rows.Close()

	var records []Loan3Record
	for rows.Next() {
		var r Loan3Record
		if err := rows.Scan(
			&r.CT_NO, &r.PS_NAME, &r.DUE_AMNT, &r.NOTPAY_AMNT, &r.PRICE,
			&r.PAYDUE_COUNT, &r.PAYAMNT, &r.BL_DUE_1,
			&r.XSTATUS, &r.LOCK_STATUS, &r.ZONE_CODE, &r.DF_ADDRHOME,
			&r.DF_TUNAME, &r.DF_AMNAME, &r.DF_PRNAME,
			&r.STNPY, &r.NOTPAY_COUNT, &r.STNON, &r.NON_COUNT,
			&r.PRODUCT_ID, &r.PRODUCT_NAME, &r.SERIE_NO, &r.GROUP_NO, &r.TYPE_NO,
			&r.BRAND_NAME, &r.FML_NAME, &r.OCCUPATION_NAME, &r.L_TYPE,
			&r.UPDATE_Y, &r.UPDATE_M, &r.EMP_NAME,
		); err != nil {
			log.Println("Error scanning Loan3 row:", err)
			continue
		}
		records = append(records, r)
	}
	return records
}

// FetchLoan3AvailablePeriods ดึงรายการปีและเดือนที่มีข้อมูลในฐานข้อมูล
func FetchLoan3AvailablePeriods(db *sql.DB) []LoanPeriod {
	rows, err := db.Query(`
		SELECT UPDATE_Y, UPDATE_M 
		FROM CONFIG.dbo.LOAN3_CSV 
		GROUP BY UPDATE_Y, UPDATE_M
		ORDER BY UPDATE_Y DESC, CAST(UPDATE_M AS INT) DESC
	`)
	if err != nil {
		log.Println("Error fetching available periods:", err)
		return nil
	}
	defer rows.Close()

	var periods []LoanPeriod
	for rows.Next() {
		var p LoanPeriod
		if err := rows.Scan(&p.Year, &p.Month); err == nil {
			periods = append(periods, p)
		}
	}
	return periods
}

// FetchLoan3OverallSummary ดึงสรุปจำนวนแยกตามกลุ่มของเดือนที่กำหนด
func FetchLoan3OverallSummary(db *sql.DB, year, month string) GroupSummary {
	var summary GroupSummary
	// 1. หาเดือนล่าสุดถ้าไม่ได้ระบุ
	if year == "" || month == "" {
		err := db.QueryRow(`
			SELECT TOP 1 UPDATE_Y, UPDATE_M 
			FROM CONFIG.dbo.LOAN3_CSV 
			ORDER BY UPDATE_Y DESC, CAST(UPDATE_M AS INT) DESC
		`).Scan(&year, &month)
		if err != nil {
			return summary
		}
	}

	// 2. นับจำนวนรายแยกตามกลุ่ม และมูลค่ารวม (จากตารางหลัก)
	rows, err := db.Query(`
		SELECT 
			c.L_TYPE, 
			COUNT(c.CT_NO) as cnt,
			SUM(ISNULL(h.due_amnt, 0)) as price
		FROM CONFIG.dbo.LOAN3_CSV c
		LEFT JOIN EHONGDB.dbo.hps_ctmain h ON h.ct_no = c.CT_NO
		WHERE c.UPDATE_Y = @p1 AND c.UPDATE_M = @p2 AND (c.US_NAME IS NULL OR c.US_NAME = '')
		GROUP BY c.L_TYPE
	`, sql.Named("p1", year), sql.Named("p2", month))
	if err != nil {
		log.Println("Error summarizing groups:", err)
		return summary
	}
	defer rows.Close()

	for rows.Next() {
		var lType string
		var count int
		var price float64
		if err := rows.Scan(&lType, &count, &price); err == nil {
			summary.TotalCount += count
			summary.TotalPrice += price
			lType = strings.TrimSpace(lType)
			switch lType {
			case "1":
				summary.G1Count = count
				summary.G1Price = price
			case "2":
				summary.G2Count = count
				summary.G2Price = price
			case "3":
				summary.G3Count = count
				summary.G3Price = price
			case "NPL":
				summary.GNPLCount = count
				summary.GNPLPrice = price
			}
		}
	}

	return summary
}
