package controllers

import (
	"strings"

	"github.com/gofiber/fiber/v2"
	"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
	"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
)

// ─── Vistas ──────────────────────────────────────────────────────────────────

func WebSmsConfigPage(c *fiber.Ctx) error {
	cfg, _ := models.GetWebSmsConfig()
	return c.Render("websms_config", fiber.Map{
		"user":    c.Locals("user"),
		"modules": c.Locals("userModules"),
		"cfg":     cfg,
	}, "layouts/main")
}

// ─── API ─────────────────────────────────────────────────────────────────────

func GetWebSmsConfig(c *fiber.Ctx) error {
	cfg, err := models.GetWebSmsConfig()
	if err != nil {
		return c.JSON(fiber.Map{"data": nil})
	}
	return c.JSON(fiber.Map{"data": cfg})
}

func SaveWebSmsConfig(c *fiber.Ctx) error {
	type body struct {
		ID       uint   `json:"id"`
		Username string `json:"username"`
		ApiToken string `json:"api_token"`
		Sender   string `json:"sender"`
		Notas    string `json:"notas"`
	}
	var b body
	if err := c.BodyParser(&b); err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
	}
	if b.Username == "" {
		return c.Status(400).JSON(fiber.Map{"error": "username es requerido"})
	}
	if b.ApiToken == "" {
		return c.Status(400).JSON(fiber.Map{"error": "api_token es requerido"})
	}

	cfg := models.WebSmsConfig{
		Username: b.Username,
		ApiToken: b.ApiToken,
		Sender:   b.Sender,
		Notas:    b.Notas,
	}
	cfg.ID = b.ID

	if err := models.SaveWebSmsConfig(cfg); err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}
	return c.JSON(fiber.Map{"message": "Configuración WebSMS guardada"})
}

func TestWebSms(c *fiber.Ctx) error {
	type body struct {
		Para    string `json:"para"`
		Mensaje string `json:"mensaje"`
	}
	var b body
	if err := c.BodyParser(&b); err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
	}
	if b.Para == "" {
		return c.Status(400).JSON(fiber.Map{"error": "número de destino requerido"})
	}
	if b.Mensaje == "" {
		b.Mensaje = "[TEST] Notificación desde U-site vía WebSMS"
	}

	cfg, err := models.GetWebSmsConfig()
	if err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "WebSMS no configurado"})
	}

	resp, err := services.SendWebSms(cfg, b.Para, b.Mensaje)
	if err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}

	models.CreateWebSmsLog(&models.WebSmsLog{
		Para:    b.Para,
		Mensaje: b.Mensaje,
		Status:  resp.Code,
		MsgID:   resp.MsgID(),
	})

	return c.JSON(fiber.Map{"ok": true, "response": resp})
}

func GetWebSmsLogs(c *fiber.Ctx) error {
	logs, err := models.GetWebSmsLogs(50)
	if err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}
	return c.JSON(logs)
}

func GetWebSmsWebhookLogs(c *fiber.Ctx) error {
	logs, err := models.GetWebSmsWebhookLogs(50)
	if err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}
	return c.JSON(logs)
}

// ─── Webhooks entrantes ─────────────────────────────────────────────────────

func WebSmsDeliveryWebhook(c *fiber.Ctx) error {
	var payload services.WebSmsAckPayload
	if err := c.BodyParser(&payload); err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
	}
	raw := c.Body()
	models.CreateWebSmsWebhookLog(&models.WebSmsWebhookLog{
		Tipo:   "delivery",
		MsgID:  payload.ID,
		Para:   payload.Msisdn,
		Status: payload.Status,
		Raw:    string(raw),
	})
	return c.SendStatus(200)
}

func WebSmsClickWebhook(c *fiber.Ctx) error {
	var payload services.WebSmsClickPayload
	if err := c.BodyParser(&payload); err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
	}
	raw := c.Body()
	models.CreateWebSmsWebhookLog(&models.WebSmsWebhookLog{
		Tipo:   "click",
		MsgID:  payload.ID,
		Para:   payload.Msisdn,
		Status: "clicked",
		Raw:    string(raw),
	})
	return c.SendStatus(200)
}

// ─── API pública ────────────────────────────────────────────────────────────

// ApiSendSms envía un SMS. Requiere Authorization: Bearer <secret_key>.
// POST /api/sms/send  { "numero": "573001234567", "mensaje": "Hola" }
func ApiSendSms(c *fiber.Ctx) error {
	bearer := strings.TrimPrefix(c.Get("Authorization"), "Bearer ")
	if bearer == "" {
		return c.Status(401).JSON(fiber.Map{"error": "token requerido"})
	}

	cfg, err := models.GetWebSmsConfig()
	if err != nil {
		return c.Status(503).JSON(fiber.Map{"error": "WebSMS no configurado"})
	}
	if cfg.SecretKey == "" || cfg.SecretKey != bearer {
		return c.Status(401).JSON(fiber.Map{"error": "token inválido"})
	}

	type body struct {
		Numero  string `json:"numero"`
		Mensaje string `json:"mensaje"`
	}
	var b body
	if err := c.BodyParser(&b); err != nil || b.Numero == "" || b.Mensaje == "" {
		return c.Status(400).JSON(fiber.Map{"error": "numero y mensaje son requeridos"})
	}

	resp, err := services.SendWebSms(cfg, b.Numero, b.Mensaje)
	errStr := ""
	status := "ok"
	if err != nil {
		errStr = err.Error()
		status = "error"
	} else if resp != nil {
		status = resp.Code
	}

	models.CreateWebSmsLog(&models.WebSmsLog{
		Para:    b.Numero,
		Mensaje: b.Mensaje,
		Status:  status,
		MsgID:   func() string { if resp != nil { return resp.MsgID() }; return "" }(),
		Error:   errStr,
	})

	if err != nil {
		return c.Status(500).JSON(fiber.Map{"error": errStr})
	}
	return c.JSON(fiber.Map{"ok": true, "id": resp.MsgID()})
}

func WebSmsIncomingWebhook(c *fiber.Ctx) error {
	var payload services.WebSmsIncomingPayload
	if err := c.BodyParser(&payload); err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "body inválido"})
	}
	raw := c.Body()
	models.CreateWebSmsWebhookLog(&models.WebSmsWebhookLog{
		Tipo:   "incoming",
		MsgID:  payload.ID,
		Para:   payload.Msisdn,
		Status: "received",
		Raw:    string(raw),
	})
	return c.SendStatus(200)
}
