package routes

import (
	"bssapp-backend/auth"
	"bssapp-backend/models"
	"bssapp-backend/queries"
	"bytes"
	"database/sql"
	"fmt"
	"log"
	"net/http"
	"runtime/debug"
	"strings"
	"time"

	"github.com/jung-kurt/gofpdf"
)

func ExportStatementAgingPDFHandler(_ *sql.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if rec := recover(); rec != nil {
				stack := string(debug.Stack())
				log.Printf("❌ ExportStatementAgingPDFHandler panic: %v\n%s", rec, stack)
				http.Error(w, fmt.Sprintf("pdf panic: %v\n%s", rec, stack), http.StatusInternalServerError)
			}
		}()

		claims, ok := auth.GetClaimsFromContext(r.Context())
		if !ok || claims == nil {
			http.Error(w, "unauthorized", http.StatusUnauthorized)
			return
		}

		selectedDate := strings.TrimSpace(r.URL.Query().Get("enddate"))
		if selectedDate == "" {
			selectedDate = strings.TrimSpace(r.URL.Query().Get("selected_date"))
		}
		if selectedDate == "" {
			selectedDate = time.Now().Format("2006-01-02")
		}

		params := models.CustomerBalanceListParams{
			SelectedDate: selectedDate,
			CariSearch:   strings.TrimSpace(r.URL.Query().Get("cari_search")),
			CariIlkGrup:  strings.TrimSpace(r.URL.Query().Get("cari_ilk_grup")),
			Piyasa:       strings.TrimSpace(r.URL.Query().Get("piyasa")),
			Temsilci:     strings.TrimSpace(r.URL.Query().Get("temsilci")),
			RiskDurumu:   strings.TrimSpace(r.URL.Query().Get("risk_durumu")),
			IslemTipi:    strings.TrimSpace(r.URL.Query().Get("islem_tipi")),
			Ulke:         strings.TrimSpace(r.URL.Query().Get("ulke")),
			Il:           strings.TrimSpace(r.URL.Query().Get("il")),
			Ilce:         strings.TrimSpace(r.URL.Query().Get("ilce")),
		}
		if accountCode := strings.TrimSpace(r.URL.Query().Get("accountcode")); accountCode != "" {
			params.CariSearch = accountCode
		}

		if err := queries.RebuildStatementAgingCache(r.Context()); err != nil {
			http.Error(w, "Error rebuilding aging cache: "+err.Error(), http.StatusInternalServerError)
			return
		}

		detailed := parseBoolQuery(r.URL.Query().Get("detailed"))
		excludeZero12 := parseBoolQuery(r.URL.Query().Get("exclude_zero_12"))
		excludeZero13 := parseBoolQuery(r.URL.Query().Get("exclude_zero_13"))

		rows, err := queries.GetStatementAgingBalanceList(r.Context(), params)
		if err != nil {
			http.Error(w, "db error: "+err.Error(), http.StatusInternalServerError)
			return
		}

		rows = filterCustomerBalanceRowsForPDF(rows, excludeZero12, excludeZero13)
		summaries, detailsByMaster := buildCustomerBalancePDFData(rows)
		sortBy := strings.TrimSpace(r.URL.Query().Get("sort_by"))
		sortDesc := parseBoolQuery(r.URL.Query().Get("sort_desc"))
		sortBalanceSummariesForPDF(summaries, sortBy, sortDesc)

		pdf := gofpdf.New("L", "mm", "A4", "")
		pdf.SetMargins(8, 8, 8)
		pdf.SetAutoPageBreak(false, 12)
		if err := registerDejavuFonts(pdf, "dejavu"); err != nil {
			http.Error(w, "pdf font error: "+err.Error(), http.StatusInternalServerError)
			return
		}

		if err := safeDrawCustomerBalancePDF(
			pdf,
			selectedDate,
			params.CariSearch,
			detailed,
			"Cari Yaslandirmali Ekstre",
			true,
			summaries,
			detailsByMaster,
		); err != nil {
			pdf = gofpdf.New("L", "mm", "A4", "")
			pdf.SetMargins(8, 8, 8)
			pdf.SetAutoPageBreak(true, 12)
			if ferr := registerDejavuFonts(pdf, "dejavu"); ferr != nil {
				http.Error(w, "pdf font error: "+ferr.Error(), http.StatusInternalServerError)
				return
			}
			drawCustomerBalancePDFFallback(pdf, selectedDate, params.CariSearch, "Cari Yaslandirmali Ekstre", summaries, true)
		}

		if err := pdf.Error(); err != nil {
			http.Error(w, "pdf render error: "+err.Error(), http.StatusInternalServerError)
			return
		}

		var buf bytes.Buffer
		if err := pdf.Output(&buf); err != nil {
			http.Error(w, "pdf output error: "+err.Error(), http.StatusInternalServerError)
			return
		}

		filename := "account-aging-summary.pdf"
		if detailed {
			filename = "account-aging-detailed.pdf"
		}

		w.Header().Set("Content-Type", "application/pdf")
		w.Header().Set("Content-Disposition", fmt.Sprintf("inline; filename=%q", filename))
		_, _ = w.Write(buf.Bytes())
	}
}
