package handlers

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"git.espin.casa/albert/cml04-mediciones/internal/client"
	"git.espin.casa/albert/cml04-mediciones/internal/types"
	"github.com/julienschmidt/httprouter"
	"github.com/xuri/excelize/v2"
)

const (
	ExcelFile  = "mediciones.xlsx"
	ExcelSheet = "Mediciones"
)

func CreateExcelSheet(ctx context.Context, mediciones []types.Mediciones) ([]byte, error) {
	// open excel file
	f, err := excelize.OpenFile(ExcelFile)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	// iterate over mediciones
	for i, medicion := range mediciones {
		f.SetCellValue(ExcelSheet, fmt.Sprintf("A%d", i+2), medicion.Producto)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("B%d", i+2), medicion.Calidad)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("C%d", i+2), medicion.Operador)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("D%d", i+2), medicion.CreatedAt.Format("02/01/2006"))
		f.SetCellValue(ExcelSheet, fmt.Sprintf("E%d", i+2), medicion.CreatedAt.Format("15:04:05"))
		f.SetCellValue(ExcelSheet, fmt.Sprintf("F%d", i+2), medicion.POrderNo)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("G%d", i+2), medicion.IDBarra)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("H%d", i+2), medicion.Colada)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("I%d", i+2), medicion.GetMedicionTipo())
		f.SetCellValue(ExcelSheet, fmt.Sprintf("J%d", i+2), medicion.MasaUnitaria.Longitud)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("K%d", i+2), medicion.MasaUnitaria.Peso)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("L%d", i+2), medicion.MasaUnitaria.GramosMM)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("M%d", i+2), medicion.AlturaPerfil)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("N%d", i+2), medicion.EspesorAlma)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("O%d", i+2), medicion.EspesoresAlas.LadoMotorInf)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("P%d", i+2), medicion.EspesoresAlas.LadoMotorSup)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("Q%d", i+2), medicion.EspesoresAlas.LadoOperadorInf)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("R%d", i+2), medicion.EspesoresAlas.LadoOperadorSup)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("S%d", i+2), medicion.AnchuraAlas.LadoOperador)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("T%d", i+2), medicion.AnchuraAlas.LadoMotor)
		f.SetCellValue(ExcelSheet, fmt.Sprintf("U%d", i+2), (medicion.AsimetriaAlma.LadoMotorSup - medicion.AsimetriaAlma.LadoMotorInf))
		f.SetCellValue(ExcelSheet, fmt.Sprintf("V%d", i+2), (medicion.AsimetriaAlma.LadoOperadorSup - medicion.AsimetriaAlma.LadoOperadorInf))
		f.SetCellValue(ExcelSheet, fmt.Sprintf("W%d", i+2), (medicion.Observaciones))
	}
	// write excel file to buffer
	buffer, err := f.WriteToBuffer()
	if err != nil {
		return nil, err
	}
	// return
	return buffer.Bytes(), nil
}

func ReportHandler(client client.IMediciones) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
		// parse form values
		if err := r.ParseForm(); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		// get dates
		fechaInicio := r.FormValue("fecha-inicio")
		fechaFinal := r.FormValue("fecha-final")
		// get product
		producto := r.FormValue("producto")
		// parse time strings
		sInicio, err := time.Parse("2006-01-02T15:04", fechaInicio)
		// handle error
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		// parse time strings
		sFinal, err := time.Parse("2006-01-02T15:04", fechaFinal)
		// handle error
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		// api request
		request := types.GetExcelReq{
			Sender:    "mediciones-ui",
			Product:   producto,
			StartTime: sInicio.Format("02/01/2006 15:04:05"),
			EndTime:   sFinal.Format("02/01/2006 15:04:05"),
			TimeStamp: time.Now().UTC().Format(time.RFC3339),
		}
		// requesting
		res, err := client.GetExcelData(
			r.Context(),
			request,
		)
		// handle error
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		// create excel file
		data, err := CreateExcelSheet(r.Context(), res.Mediciones)
		// handle error
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		downloadName := time.Now().UTC().Format("mediciones-20060102150405.xlsx")
		// set header content type
		w.Header().Set("Content-type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
		w.Header().Set("Content-Description", "File Transfer")
		w.Header().Set("Content-Disposition", "attachment; filename="+downloadName)
		// write header 200
		w.WriteHeader(http.StatusOK)
		// write response
		w.Write(data)
	}
}
