// queries/statements_pdf.go
package queries

import (
	"bssapp-backend/db"
	"bssapp-backend/models"
	"database/sql"
	"fmt"
	"log"
	"strings"
)

// küçük yardımcı: boşlukları temizle, her değeri ayrı tırnakla sar
func buildQuotedList(vals []string) string {
	var pp []string
	for _, v := range vals {
		v = strings.TrimSpace(v)
		if v != "" {
			pp = append(pp, fmt.Sprintf("'%s'", v)) // '1','2' gibi
		}
	}
	if len(pp) == 0 {
		return ""
	}
	return strings.Join(pp, ",")
}

/* ============================ HEADER (Ana Tablo) ============================ */

func GetStatementsPDF(accountCode, startDate, endDate string, parislemler []string) ([]models.StatementHeader, []string, error) {
	// Account normalize
	if len(accountCode) == 7 && strings.ContainsAny(accountCode, "0123456789") {
		accountCode = accountCode[:3] + " " + accountCode[3:]
	}

	// IN list parse et
	inList := buildQuotedList(parislemler)
	parislemCond := "''"
	if inList != "" {
		parislemCond = inList
	}

	query := fmt.Sprintf(`
;WITH Opening AS (
    SELECT 
        b.CurrAccCode AS Cari_Kod,
        b.DocCurrencyCode AS Para_Birimi,
        SUM(c.Debit - c.Credit) AS Devir_Bakiyesi
    FROM trCurrAccBook b
    LEFT JOIN trCurrAccBookCurrency c
      ON c.CurrAccBookID = b.CurrAccBookID
     AND c.CurrencyCode  = b.DocCurrencyCode
    WHERE b.CurrAccCode LIKE @Carikod
      AND b.DocumentDate < @StartDate
      AND EXISTS (
            SELECT 1
            FROM CurrAccBookATAttributesFilter f2
            WHERE f2.CurrAccBookID = b.CurrAccBookID
              AND f2.ATAtt01 IN (%s)
      )
    GROUP BY b.CurrAccCode, b.DocCurrencyCode
),
Movements AS (
    SELECT 
        b.CurrAccCode        AS Cari_Kod,
        d.CurrAccDescription AS Cari_Isim,
        CONVERT(varchar(10), b.DocumentDate, 23) AS Belge_Tarihi, 
        CONVERT(varchar(10), b.DueDate, 23)      AS Vade_Tarihi, 
        b.RefNumber          AS Belge_No,
        b.BaseApplicationCode AS Islem_Tipi,
        b.LineDescription    AS Aciklama,
        b.DocCurrencyCode    AS Para_Birimi,
        c.Debit              AS Borc,
        c.Credit             AS Alacak,
        SUM(c.Debit - c.Credit)
            OVER (PARTITION BY b.CurrAccCode, c.CurrencyCode 
                  ORDER BY b.DocumentDate, b.CurrAccBookID) AS Hareket_Bakiyesi,
        f.ATAtt01 AS Parislemler
    FROM trCurrAccBook b
    LEFT JOIN cdCurrAccDesc d
        ON b.CurrAccCode = d.CurrAccCode AND d.LangCode = 'TR'
    LEFT JOIN trCurrAccBookCurrency c
        ON b.CurrAccBookID = c.CurrAccBookID
       AND b.DocCurrencyCode = c.CurrencyCode
    LEFT JOIN CurrAccBookATAttributesFilter f
        ON b.CurrAccBookID = f.CurrAccBookID
    WHERE b.CurrAccCode LIKE @Carikod
      AND b.DocumentDate BETWEEN @StartDate AND @EndDate
      AND EXISTS (
            SELECT 1 
            FROM CurrAccBookATAttributesFilter f2
            WHERE f2.CurrAccBookID = b.CurrAccBookID
              AND f2.ATAtt01 IN (%s)
      )
)`, parislemCond, parislemCond)
	query += fmt.Sprintf(`
SELECT 
    m.Cari_Kod,
    m.Cari_Isim,
    m.Belge_Tarihi,
    m.Vade_Tarihi,
    m.Belge_No,
    m.Islem_Tipi,
    m.Aciklama,
    m.Para_Birimi,
    m.Borc,
    m.Alacak,
    ISNULL(o.Devir_Bakiyesi,0) + m.Hareket_Bakiyesi AS Bakiye,
    m.Parislemler
FROM Movements m
LEFT JOIN Opening o
  ON o.Cari_Kod = m.Cari_Kod
 AND o.Para_Birimi = m.Para_Birimi

UNION ALL

-- Devir satırı
SELECT  
    @Carikod                    AS Cari_Kod,
    MAX(d.CurrAccDescription)   AS Cari_Isim,
    CONVERT(varchar(10), @StartDate, 23) AS Belge_Tarihi, 
    CONVERT(varchar(10), @StartDate, 23) AS Vade_Tarihi, 
    'Baslangic_devir'           AS Belge_No,
    'Devir'                     AS Islem_Tipi,
    'Devir Bakiyesi'            AS Aciklama,
    b.DocCurrencyCode           AS Para_Birimi,
    SUM(c.Debit)                AS Borc,
    SUM(c.Credit)               AS Alacak,
    SUM(c.Debit) - SUM(c.Credit) AS Bakiye,
    (
      SELECT STRING_AGG(x.ATAtt01, ',')
      FROM (
        SELECT DISTINCT f2.ATAtt01
        FROM CurrAccBookATAttributesFilter f2
        INNER JOIN trCurrAccBook bb
          ON f2.CurrAccBookID = bb.CurrAccBookID
        WHERE bb.CurrAccCode LIKE @Carikod
          AND bb.DocumentDate < @StartDate
          AND f2.ATAtt01 IN (%s)
      ) x
    ) AS Parislemler
FROM trCurrAccBook b
LEFT JOIN cdCurrAccDesc d
    ON b.CurrAccCode = d.CurrAccCode AND d.LangCode = 'TR'
LEFT JOIN trCurrAccBookCurrency c
    ON b.CurrAccBookID = c.CurrAccBookID
   AND b.DocCurrencyCode = c.CurrencyCode
WHERE b.CurrAccCode LIKE @Carikod
  AND b.DocumentDate < @StartDate
GROUP BY b.DocCurrencyCode

ORDER BY Para_Birimi, Belge_Tarihi;`, parislemCond)

	rows, err := db.MssqlDB.Query(query,
		sql.Named("Carikod", "%"+accountCode+"%"),
		sql.Named("StartDate", startDate),
		sql.Named("EndDate", endDate),
	)
	if err != nil {
		log.Printf("❌ Header sorgu hatası: %v", err)
		return nil, nil, fmt.Errorf("header sorgu hatası: %v", err)
	}
	defer rows.Close()

	var headers []models.StatementHeader
	var belgeNos []string
	for rows.Next() {
		var h models.StatementHeader
		if err := rows.Scan(
			&h.CariKod, &h.CariIsim,
			&h.BelgeTarihi, &h.VadeTarihi,
			&h.BelgeNo, &h.IslemTipi,
			&h.Aciklama, &h.ParaBirimi,
			&h.Borc, &h.Alacak,
			&h.Bakiye, &h.Parislemler,
		); err != nil {
			log.Printf("❌ Header scan hatası: %v", err)
			return nil, nil, err
		}
		headers = append(headers, h)
		if h.BelgeNo != "" {
			belgeNos = append(belgeNos, h.BelgeNo)
		}
	}
	log.Printf("✅ Header verileri alındı: %d kayıt, %d belge no", len(headers), len(belgeNos))
	return headers, belgeNos, nil
}

/* ============================ DETAIL (Alt Tablo) ============================ */

func GetDetailsMapPDF(belgeNos []string, startDate, endDate string) (map[string][]models.StatementDetail, error) {
	result := make(map[string][]models.StatementDetail)
	if len(belgeNos) == 0 {
		log.Println("⚠️ GetDetailsMapPDF: belge listesi boş")
		return result, nil
	}

	qs := make([]string, 0, len(belgeNos))
	for _, no := range belgeNos {
		safe := strings.ReplaceAll(no, "'", "''")
		qs = append(qs, fmt.Sprintf("'%s'", safe))
	}
	inBelge := strings.Join(qs, ",")

	query := fmt.Sprintf(`
;WITH BookMap AS (
  SELECT b.RefNumber AS InvoiceNumber, b.CurrAccBookID
  FROM trCurrAccBook b
  WHERE b.RefNumber IN (%s)
)
SELECT
    CONVERT(varchar(10), a.InvoiceDate, 23) AS Belge_Tarihi,
    a.InvoiceNumber AS Belge_Ref_Numarasi,

   MAX(ISNULL(AnaGrupDesc.AttributeDescription, '')) AS Urun_Ana_Grubu,
   MAX(ISNULL(AltGrupDesc.AttributeDescription, '')) AS Urun_Alt_Grubu,
   MAX(ISNULL(GarsonDesc.AttributeDescription, ''))  AS Yetiskin_Garson,
   MAX(ISNULL(FitDesc.AttributeDescription, ''))     AS Fit,
   MAX(ISNULL(KisaKarDesc.AttributeDescription, '')) AS Icerik,

    a.ItemCode, a.ColorCode,
    SUM(a.Qty1), SUM(ABS(a.Doc_Price)),
    CAST(SUM(a.Qty1 * ABS(a.Doc_Price)) AS numeric(18,2))

FROM AllInvoicesWithAttributes a
JOIN BookMap bm
  ON bm.InvoiceNumber = a.InvoiceNumber

-- Ana Grup
LEFT JOIN prItemAttribute AnaGrup
  ON a.ItemCode = AnaGrup.ItemCode AND AnaGrup.AttributeTypeCode = 1
LEFT JOIN cdItemAttributeDesc AnaGrupDesc
  ON AnaGrup.AttributeTypeCode = AnaGrupDesc.AttributeTypeCode
 AND AnaGrup.AttributeCode     = AnaGrupDesc.AttributeCode
 AND AnaGrup.ItemTypeCode      = AnaGrupDesc.ItemTypeCode

-- Alt Grup
LEFT JOIN prItemAttribute AltGrup
  ON a.ItemCode = AltGrup.ItemCode AND AltGrup.AttributeTypeCode = 2
LEFT JOIN cdItemAttributeDesc AltGrupDesc
  ON AltGrup.AttributeTypeCode = AltGrupDesc.AttributeTypeCode
 AND AltGrup.AttributeCode     = AltGrupDesc.AttributeCode
 AND AltGrup.ItemTypeCode      = AltGrupDesc.ItemTypeCode

-- Garson
LEFT JOIN prItemAttribute Garson
  ON a.ItemCode = Garson.ItemCode AND Garson.AttributeTypeCode = 44
LEFT JOIN cdItemAttributeDesc GarsonDesc
  ON Garson.AttributeTypeCode = GarsonDesc.AttributeTypeCode
 AND Garson.AttributeCode     = GarsonDesc.AttributeCode
 AND Garson.ItemTypeCode      = GarsonDesc.ItemTypeCode

-- Fit
LEFT JOIN prItemAttribute FitTbl
  ON a.ItemCode = FitTbl.ItemCode AND FitTbl.AttributeTypeCode = 38
LEFT JOIN cdItemAttributeDesc FitDesc
  ON FitTbl.AttributeTypeCode = FitDesc.AttributeTypeCode
 AND FitTbl.AttributeCode     = FitDesc.AttributeCode
 AND FitTbl.ItemTypeCode      = FitDesc.ItemTypeCode

-- Kısa Karışım
LEFT JOIN prItemAttribute KisaKar
  ON a.ItemCode = KisaKar.ItemCode AND KisaKar.AttributeTypeCode = 41
LEFT JOIN cdItemAttributeDesc KisaKarDesc
  ON KisaKar.AttributeTypeCode = KisaKarDesc.AttributeTypeCode
 AND KisaKar.AttributeCode     = KisaKarDesc.AttributeCode
 AND KisaKar.ItemTypeCode      = KisaKarDesc.ItemTypeCode

WHERE a.InvoiceDate BETWEEN @StartDate AND @EndDate
GROUP BY a.InvoiceDate, a.InvoiceNumber, a.ItemCode, a.ColorCode
ORDER BY a.InvoiceNumber, a.ItemCode, a.ColorCode;`, inBelge)
	rows, err := db.MssqlDB.Query(query,
		sql.Named("StartDate", startDate),
		sql.Named("EndDate", endDate),
	)
	if err != nil {
		log.Printf("❌ Detay sorgu hatası: %v", err)
		return nil, fmt.Errorf("detay sorgu hatası: %v", err)
	}
	defer rows.Close()

	for rows.Next() {
		var d models.StatementDetail
		if err := rows.Scan(
			&d.BelgeTarihi,
			&d.BelgeRefNumarasi,
			&d.UrunAnaGrubu,
			&d.UrunAltGrubu,
			&d.YetiskinGarson,
			&d.Fit,
			&d.Icerik,
			&d.UrunKodu,
			&d.UrunRengi,
			&d.ToplamAdet,
			&d.ToplamFiyat,
			&d.ToplamTutar,
		); err != nil {
			log.Printf("❌ Detay scan hatası: %v", err)
			return nil, err
		}
		result[d.BelgeRefNumarasi] = append(result[d.BelgeRefNumarasi], d)
	}
	log.Printf("✅ Detay verileri alındı: %d belge için detay var", len(result))
	return result, nil
}
