package admin

import (
	"bytes"
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"time"

	"verification-platform-backend/internal/database"
	"verification-platform-backend/internal/model"
	"verification-platform-backend/internal/service"
	"verification-platform-backend/pkg/response"

	"github.com/gin-gonic/gin"
)

func handleGetWebhooks(c *gin.Context) {
	userID := c.GetUint("user_id")
	appID := c.Query("application_id")

	var webhooks []struct {
		model.WebhookConfig
		ApplicationName string `json:"application_name"`
	}

	query := database.DB.Model(&model.WebhookConfig{}).
		Select("webhook_configs.*, applications.name as application_name").
		Joins("JOIN applications ON webhook_configs.application_id = applications.id").
		Where("applications.user_id = ?", userID)

	if appID != "" && appID != "all" {
		query = query.Where("webhook_configs.application_id = ?", appID)
	}

	if err := query.Find(&webhooks).Error; err != nil {
		response.Error(c, 500, "获取Webhook配置失败")
		return
	}

	response.Success(c, webhooks)
}

func handleCreateWebhook(c *gin.Context) {
	userID := c.GetUint("user_id")

	var req struct {
		ApplicationID uint     `json:"application_id" binding:"required"`
		Name          string   `json:"name" binding:"required"`
		URL           string   `json:"url" binding:"required,url"`
		SecretKey     string   `json:"secret_key"`
		Events        []string `json:"events" binding:"required"`
		RetryCount    int      `json:"retry_count"`
		Timeout       int      `json:"timeout"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误: "+err.Error())
		return
	}

	var app model.Application
	if err := database.DB.Where("id = ? AND user_id = ?", req.ApplicationID, userID).First(&app).Error; err != nil {
		response.Error(c, 404, "应用不存在")
		return
	}

	eventsJSON, _ := json.Marshal(req.Events)
	if req.RetryCount == 0 {
		req.RetryCount = 3
	}
	if req.Timeout == 0 {
		req.Timeout = 10
	}

	webhook := model.WebhookConfig{
		ApplicationID: req.ApplicationID,
		Name:          req.Name,
		URL:           req.URL,
		SecretKey:     req.SecretKey,
		Events:        string(eventsJSON),
		Status:        "active",
		RetryCount:    req.RetryCount,
		Timeout:       req.Timeout,
	}

	if err := database.DB.Create(&webhook).Error; err != nil {
		response.Error(c, 500, "创建Webhook配置失败")
		return
	}

	service.LogOperation(c, "create", "webhook", &webhook.ID, fmt.Sprintf("创建Webhook: %s", webhook.Name), nil)

	response.Success(c, webhook)
}

func handleUpdateWebhook(c *gin.Context) {
	userID := c.GetUint("user_id")

	id := c.Param("id")

	var req struct {
		Name       string   `json:"name"`
		URL        string   `json:"url" binding:"omitempty,url"`
		SecretKey  string   `json:"secret_key"`
		Events     []string `json:"events"`
		Status     string   `json:"status"`
		RetryCount int      `json:"retry_count"`
		Timeout    int      `json:"timeout"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误: "+err.Error())
		return
	}

	var webhook model.WebhookConfig
	if err := database.DB.Joins("JOIN applications ON webhook_configs.application_id = applications.id").
		Where("webhook_configs.id = ? AND applications.user_id = ?", id, userID).
		First(&webhook).Error; err != nil {
		response.Error(c, 404, "Webhook配置不存在")
		return
	}

	updates := make(map[string]interface{})
	if req.Name != "" {
		updates["name"] = req.Name
	}
	if req.URL != "" {
		updates["url"] = req.URL
	}
	if req.SecretKey != "" {
		updates["secret_key"] = req.SecretKey
	}
	if len(req.Events) > 0 {
		eventsJSON, _ := json.Marshal(req.Events)
		updates["events"] = string(eventsJSON)
	}
	if req.Status != "" {
		updates["status"] = req.Status
	}
	if req.RetryCount > 0 {
		updates["retry_count"] = req.RetryCount
	}
	if req.Timeout > 0 {
		updates["timeout"] = req.Timeout
	}

	if err := database.DB.Model(&webhook).Updates(updates).Error; err != nil {
		response.Error(c, 500, "更新Webhook配置失败")
		return
	}

	response.Success(c, webhook)
}

func handleDeleteWebhook(c *gin.Context) {
	userID := c.GetUint("user_id")

	id := c.Param("id")

	var webhook model.WebhookConfig
	if err := database.DB.Joins("JOIN applications ON webhook_configs.application_id = applications.id").
		Where("webhook_configs.id = ? AND applications.user_id = ?", id, userID).
		First(&webhook).Error; err != nil {
		response.Error(c, 404, "Webhook配置不存在")
		return
	}

	webhookName := webhook.Name
	webhookID := webhook.ID

	if err := database.DB.Delete(&webhook).Error; err != nil {
		response.Error(c, 500, "删除Webhook配置失败")
		return
	}

	service.LogOperation(c, "delete", "webhook", &webhookID, fmt.Sprintf("删除Webhook: %s", webhookName), nil)

	response.Success(c, nil)
}

func handleGetWebhookLogs(c *gin.Context) {
	userID := c.GetUint("user_id")
	webhookID := c.Query("webhook_id")
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))

	var logs []model.WebhookLog
	var total int64

	query := database.DB.Model(&model.WebhookLog{}).
		Joins("JOIN webhook_configs ON webhook_logs.webhook_id = webhook_configs.id").
		Joins("JOIN applications ON webhook_configs.application_id = applications.id").
		Where("applications.user_id = ?", userID)

	if webhookID != "" {
		query = query.Where("webhook_logs.webhook_id = ?", webhookID)
	}

	query.Count(&total)

	offset := (page - 1) * pageSize
	if err := query.Order("webhook_logs.created_at DESC").
		Offset(offset).Limit(pageSize).
		Find(&logs).Error; err != nil {
		response.Error(c, 500, "获取Webhook日志失败")
		return
	}

	response.Success(c, gin.H{
		"logs":       logs,
		"total":      total,
		"page":       page,
		"page_size":  pageSize,
		"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
	})
}

func handleTestWebhook(c *gin.Context) {
	userID := c.GetUint("user_id")
	id := c.Param("id")

	var webhook model.WebhookConfig
	if err := database.DB.Joins("JOIN applications ON webhook_configs.application_id = applications.id").
		Where("webhook_configs.id = ? AND applications.user_id = ?", id, userID).
		First(&webhook).Error; err != nil {
		response.Error(c, 404, "Webhook配置不存在")
		return
	}

	testData := map[string]interface{}{
		"event":     "test",
		"timestamp": time.Now().Unix(),
		"data": map[string]interface{}{
			"message": "This is a test webhook",
		},
	}

	go sendWebhook(&webhook, testData)

	response.Success(c, gin.H{"message": "测试请求已发送"})
}

func handleGetAPIKeys(c *gin.Context) {
	userID := c.GetUint("user_id")
	appID := c.Query("application_id")

	var apiKeys []struct {
		model.ExtensionAPIKey
		ApplicationName string `json:"application_name"`
	}

	query := database.DB.Model(&model.ExtensionAPIKey{}).
		Select("extension_api_keys.*, applications.name as application_name").
		Joins("JOIN applications ON extension_api_keys.application_id = applications.id").
		Where("applications.user_id = ?", userID)

	if appID != "" && appID != "all" {
		query = query.Where("extension_api_keys.application_id = ?", appID)
	}

	if err := query.Find(&apiKeys).Error; err != nil {
		response.Error(c, 500, "获取API密钥失败")
		return
	}

	response.Success(c, apiKeys)
}

func handleCreateAPIKey(c *gin.Context) {
	userID := c.GetUint("user_id")

	var req struct {
		ApplicationID uint     `json:"application_id" binding:"required"`
		Name          string   `json:"name" binding:"required"`
		Permissions   []string `json:"permissions"`
		ExpiresAt     *string  `json:"expires_at"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误: "+err.Error())
		return
	}

	var app model.Application
	if err := database.DB.Where("id = ? AND user_id = ?", req.ApplicationID, userID).First(&app).Error; err != nil {
		response.Error(c, 404, "应用不存在")
		return
	}

	accessKey := generateRandomKey(32)
	secretKey := generateRandomKey(32)

	permissionsJSON, _ := json.Marshal(req.Permissions)

	apiKey := model.ExtensionAPIKey{
		ApplicationID: req.ApplicationID,
		Name:          req.Name,
		AccessKey:     accessKey,
		SecretKey:     secretKey,
		Permissions:   string(permissionsJSON),
		Status:        "active",
	}

	if req.ExpiresAt != nil {
		expiresAt, err := time.Parse(time.RFC3339, *req.ExpiresAt)
		if err == nil {
			apiKey.ExpiresAt = &expiresAt
		}
	}

	if err := database.DB.Create(&apiKey).Error; err != nil {
		response.Error(c, 500, "创建API密钥失败")
		return
	}

	response.Success(c, apiKey)
}

func handleUpdateAPIKey(c *gin.Context) {
	userID := c.GetUint("user_id")

	id := c.Param("id")

	var req struct {
		Name        string   `json:"name"`
		Permissions []string `json:"permissions"`
		Status      string   `json:"status"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误: "+err.Error())
		return
	}

	var apiKey model.ExtensionAPIKey
	if err := database.DB.Joins("JOIN applications ON extension_api_keys.application_id = applications.id").
		Where("extension_api_keys.id = ? AND applications.user_id = ?", id, userID).
		First(&apiKey).Error; err != nil {
		response.Error(c, 404, "API密钥不存在")
		return
	}

	updates := make(map[string]interface{})
	if req.Name != "" {
		updates["name"] = req.Name
	}
	if len(req.Permissions) > 0 {
		permissionsJSON, _ := json.Marshal(req.Permissions)
		updates["permissions"] = string(permissionsJSON)
	}
	if req.Status != "" {
		updates["status"] = req.Status
	}

	if err := database.DB.Model(&apiKey).Updates(updates).Error; err != nil {
		response.Error(c, 500, "更新API密钥失败")
		return
	}

	response.Success(c, apiKey)
}

func handleDeleteAPIKey(c *gin.Context) {
	userID := c.GetUint("user_id")

	id := c.Param("id")

	var apiKey model.ExtensionAPIKey
	if err := database.DB.Joins("JOIN applications ON extension_api_keys.application_id = applications.id").
		Where("extension_api_keys.id = ? AND applications.user_id = ?", id, userID).
		First(&apiKey).Error; err != nil {
		response.Error(c, 404, "API密钥不存在")
		return
	}

	if err := database.DB.Delete(&apiKey).Error; err != nil {
		response.Error(c, 500, "删除API密钥失败")
		return
	}

	response.Success(c, nil)
}

func handleRegenerateAPIKey(c *gin.Context) {
	userID := c.GetUint("user_id")
	id := c.Param("id")

	var apiKey model.ExtensionAPIKey
	if err := database.DB.Joins("JOIN applications ON extension_api_keys.application_id = applications.id").
		Where("extension_api_keys.id = ? AND applications.user_id = ?", id, userID).
		First(&apiKey).Error; err != nil {
		response.Error(c, 404, "API密钥不存在")
		return
	}

	newSecretKey := generateRandomKey(32)
	if err := database.DB.Model(&apiKey).Update("secret_key", newSecretKey).Error; err != nil {
		response.Error(c, 500, "重新生成密钥失败")
		return
	}

	apiKey.SecretKey = newSecretKey
	response.Success(c, apiKey)
}

func generateRandomKey(length int) string {
	bytes := make([]byte, length)
	if _, err := rand.Read(bytes); err != nil {
		return ""
	}
	return hex.EncodeToString(bytes)[:length*2]
}

func sendWebhook(webhook *model.WebhookConfig, data map[string]interface{}) {
	jsonData, _ := json.Marshal(data)

	startTime := time.Now()
	client := &http.Client{
		Timeout: time.Duration(webhook.Timeout) * time.Second,
	}

	req, err := http.NewRequest("POST", webhook.URL, bytes.NewReader(jsonData))
	if err != nil {
		logWebhookError(webhook.ID, data, err, time.Since(startTime).Milliseconds())
		return
	}

	req.Header.Set("Content-Type", "application/json")
	if webhook.SecretKey != "" {
		req.Header.Set("X-Webhook-Secret", webhook.SecretKey)
	}

	resp, err := client.Do(req)
	duration := time.Since(startTime).Milliseconds()

	if err != nil {
		logWebhookError(webhook.ID, data, err, duration)
		return
	}
	defer resp.Body.Close()

	logWebhookSuccess(webhook.ID, data, resp.StatusCode, duration)
}

func logWebhookSuccess(webhookID uint, requestData map[string]interface{}, statusCode int, duration int64) {
	requestJSON, _ := json.Marshal(requestData)
	log := model.WebhookLog{
		WebhookID:    webhookID,
		Event:        requestData["event"].(string),
		RequestData:  string(requestJSON),
		ResponseCode: statusCode,
		Status:       "success",
		Duration:     int(duration),
	}
	database.DB.Create(&log)
}

func logWebhookError(webhookID uint, requestData map[string]interface{}, err error, duration int64) {
	requestJSON, _ := json.Marshal(requestData)
	log := model.WebhookLog{
		WebhookID:    webhookID,
		Event:        requestData["event"].(string),
		RequestData:  string(requestJSON),
		Status:       "failed",
		ErrorMessage: err.Error(),
		Duration:     int(duration),
	}
	database.DB.Create(&log)
}

func handleUpdateWebhookStatus(c *gin.Context) {
	userID := c.GetUint("user_id")
	id := c.Param("id")

	var req struct {
		Status string `json:"status" binding:"required,oneof=active inactive"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误: "+err.Error())
		return
	}

	var webhook model.WebhookConfig
	if err := database.DB.Joins("JOIN applications ON webhook_configs.application_id = applications.id").
		Where("webhook_configs.id = ? AND applications.user_id = ?", id, userID).
		First(&webhook).Error; err != nil {
		response.Error(c, 404, "Webhook配置不存在")
		return
	}

	if err := database.DB.Model(&webhook).Update("status", req.Status).Error; err != nil {
		response.Error(c, 500, "更新状态失败")
		return
	}

	response.Success(c, webhook)
}

func handleBatchUpdateWebhookStatus(c *gin.Context) {
	userID := c.GetUint("user_id")

	var req struct {
		IDs    []uint `json:"ids" binding:"required"`
		Status string `json:"status" binding:"required,oneof=active inactive"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误: "+err.Error())
		return
	}

	if len(req.IDs) == 0 {
		response.Error(c, 400, "请选择要更新的Webhook")
		return
	}

	result := database.DB.Model(&model.WebhookConfig{}).
		Joins("JOIN applications ON webhook_configs.application_id = applications.id").
		Where("applications.user_id = ? AND webhook_configs.id IN ?", userID, req.IDs).
		Update("status", req.Status)

	if result.Error != nil {
		response.Error(c, 500, "批量更新状态失败")
		return
	}

	response.Success(c, gin.H{"updated_count": result.RowsAffected})
}

func handleBatchDeleteWebhooks(c *gin.Context) {
	userID := c.GetUint("user_id")

	var req struct {
		IDs []uint `json:"ids" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误: "+err.Error())
		return
	}

	if len(req.IDs) == 0 {
		response.Error(c, 400, "请选择要删除的Webhook")
		return
	}

	result := database.DB.Where("id IN (?) AND application_id IN (SELECT id FROM applications WHERE user_id = ?)", req.IDs, userID).
		Delete(&model.WebhookConfig{})

	if result.Error != nil {
		response.Error(c, 500, "批量删除失败")
		return
	}

	response.Success(c, gin.H{"deleted_count": result.RowsAffected})
}

func handleUpdateAPIKeyStatus(c *gin.Context) {
	userID := c.GetUint("user_id")
	id := c.Param("id")

	var req struct {
		Status string `json:"status" binding:"required,oneof=active inactive"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误: "+err.Error())
		return
	}

	var apiKey model.ExtensionAPIKey
	if err := database.DB.Joins("JOIN applications ON extension_api_keys.application_id = applications.id").
		Where("extension_api_keys.id = ? AND applications.user_id = ?", id, userID).
		First(&apiKey).Error; err != nil {
		response.Error(c, 404, "API密钥不存在")
		return
	}

	if err := database.DB.Model(&apiKey).Update("status", req.Status).Error; err != nil {
		response.Error(c, 500, "更新状态失败")
		return
	}

	response.Success(c, apiKey)
}

func handleBatchUpdateAPIKeyStatus(c *gin.Context) {
	userID := c.GetUint("user_id")

	var req struct {
		IDs    []uint `json:"ids" binding:"required"`
		Status string `json:"status" binding:"required,oneof=active inactive"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误: "+err.Error())
		return
	}

	if len(req.IDs) == 0 {
		response.Error(c, 400, "请选择要更新的API密钥")
		return
	}

	result := database.DB.Model(&model.ExtensionAPIKey{}).
		Joins("JOIN applications ON extension_api_keys.application_id = applications.id").
		Where("applications.user_id = ? AND extension_api_keys.id IN ?", userID, req.IDs).
		Update("status", req.Status)

	if result.Error != nil {
		response.Error(c, 500, "批量更新状态失败")
		return
	}

	response.Success(c, gin.H{"updated_count": result.RowsAffected})
}

func handleBatchDeleteAPIKeys(c *gin.Context) {
	userID := c.GetUint("user_id")

	var req struct {
		IDs []uint `json:"ids" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误: "+err.Error())
		return
	}

	if len(req.IDs) == 0 {
		response.Error(c, 400, "请选择要删除的API密钥")
		return
	}

	result := database.DB.Where("id IN (?) AND application_id IN (SELECT id FROM applications WHERE user_id = ?)", req.IDs, userID).
		Delete(&model.ExtensionAPIKey{})

	if result.Error != nil {
		response.Error(c, 500, "批量删除失败")
		return
	}

	response.Success(c, gin.H{"deleted_count": result.RowsAffected})
}
