package controllers

import (
	"fotbal-club/internal/models"

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

// ExampleUsageController demonstrates how to use the new utility controllers
type ExampleUsageController struct {
	DB *gorm.DB
}

// NewExampleUsageController creates a new ExampleUsageController instance
func NewExampleUsageController(db *gorm.DB) *ExampleUsageController {
	return &ExampleUsageController{DB: db}
}

// ===== EXAMPLE 1: Simple List with Pagination =====
// GET /api/v1/articles?page=1&page_size=20
func (euc *ExampleUsageController) ListArticlesWithPagination(c *gin.Context) {
	query := euc.DB.Model(&models.Article{}).Where("published = ?", true)

	var articles []models.Article
	meta, err := Paginator.Paginate(c, query, &articles)
	if err != nil {
		Respond.InternalError(c, "Failed to retrieve articles")
		return
	}

	Respond.SuccessWithMeta(c, articles, meta, "Articles retrieved successfully")
}

// ===== EXAMPLE 2: List with Search, Sort, and Pagination =====
// GET /api/v1/articles?search=football&sort=created_at:desc&page=1&page_size=20
func (euc *ExampleUsageController) ListArticlesWithFilters(c *gin.Context) {
	query := QueryParser.BuildQueryChain(c, euc.DB.Model(&models.Article{})).
		WithSearch("title", "content").
		WithSort("created_at", "desc").
		Build()

	var articles []models.Article
	meta, err := Paginator.PaginateWithPreload(c, query, &articles, "Author", "Category")
	if err != nil {
		Respond.InternalError(c, "Failed to retrieve articles")
		return
	}

	Respond.SuccessWithMeta(c, articles, meta, "Articles retrieved successfully")
}

// ===== EXAMPLE 3: Create with Validation =====
func (euc *ExampleUsageController) CreateArticleWithValidation(c *gin.Context) {
	var req struct {
		Title   string `json:"title" validate:"required,min=3,max=200"`
		Content string `json:"content" validate:"required,min=10"`
		Slug    string `json:"slug" validate:"omitempty,slug"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		Respond.BadRequest(c, "Invalid JSON: "+err.Error())
		return
	}

	// Validate using our helper
	if !Validator.ValidateAndRespond(c, req) {
		return // Response already sent
	}

	// Sanitize inputs
	req.Title = Validator.SanitizeString(req.Title)
	req.Slug = Validator.SanitizeSlug(req.Slug)

	article := models.Article{
		Title:   req.Title,
		Content: req.Content,
		Slug:    req.Slug,
	}

	if err := euc.DB.Create(&article).Error; err != nil {
		Respond.InternalError(c, "Failed to create article")
		return
	}

	// Log the creation
	if AuditLogger != nil {
		_ = AuditLogger.LogCreate(c, "Article", article.ID, "Article created: "+article.Title)
	}

	Respond.Created(c, article, "Article created successfully")
}

// ===== EXAMPLE 4: Update with Audit Logging =====
func (euc *ExampleUsageController) UpdateArticleWithAudit(c *gin.Context) {
	id := c.Param("id")

	var article models.Article
	if err := euc.DB.First(&article, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			Respond.NotFound(c, "Article not found")
			return
		}
		Respond.InternalError(c, "Failed to retrieve article")
		return
	}

	// Store old values for audit
	oldTitle := article.Title
	oldPublished := article.Published

	var req struct {
		Title     string `json:"title" validate:"omitempty,min=3,max=200"`
		Published *bool  `json:"published"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		Respond.BadRequest(c, "Invalid JSON: "+err.Error())
		return
	}

	if !Validator.ValidateAndRespond(c, req) {
		return
	}

	// Apply updates
	if req.Title != "" {
		article.Title = Validator.SanitizeString(req.Title)
	}
	if req.Published != nil {
		article.Published = *req.Published
	}

	if err := euc.DB.Save(&article).Error; err != nil {
		Respond.InternalError(c, "Failed to update article")
		return
	}

	// Log the update with changes
	if AuditLogger != nil {
		before := map[string]interface{}{
			"title":     oldTitle,
			"published": oldPublished,
		}
		after := map[string]interface{}{
			"title":     article.Title,
			"published": article.Published,
		}
		_ = AuditLogger.LogUpdate(c, "Article", article.ID, "Article updated", before, after)
	}

	Respond.Success(c, article, "Article updated successfully")
}

// ===== EXAMPLE 5: Batch Delete =====
// POST /api/v1/articles/batch-delete
// Body: {"ids": [1, 2, 3]}
func (euc *ExampleUsageController) BatchDeleteArticles(c *gin.Context) {
	if BatchOps == nil {
		BatchOps = NewBatchOperationsController(euc.DB)
	}
	BatchOps.BatchDelete(c, &models.Article{}, "articles")
}

// ===== EXAMPLE 6: Advanced Filtering =====
// GET /api/v1/articles?published=true&category_ids=1,2,3&from=2024-01-01&to=2024-12-31
func (euc *ExampleUsageController) ListArticlesAdvanced(c *gin.Context) {
	query := QueryParser.BuildQueryChain(c, euc.DB.Model(&models.Article{})).
		WithSearch("title", "content").
		WithSort("created_at", "desc").
		WithBoolFilter("published", "published").
		WithBoolFilter("featured", "featured").
		WithIDsFilter("category_ids", "category_id").
		WithDateRange("created_at").
		Build()

	var articles []models.Article
	meta, err := Paginator.PaginateWithPreload(c, query, &articles, "Author", "Category")
	if err != nil {
		Respond.InternalError(c, "Failed to retrieve articles")
		return
	}

	Respond.SuccessWithMeta(c, articles, meta, "Articles retrieved successfully")
}

// ===== EXAMPLE 7: Batch Publish/Unpublish =====
// POST /api/v1/articles/batch-publish
// Body: {"ids": [1, 2, 3]}
func (euc *ExampleUsageController) BatchPublishArticles(c *gin.Context) {
	if BatchOps == nil {
		BatchOps = NewBatchOperationsController(euc.DB)
	}
	BatchOps.BatchPublish(c, &models.Article{}, "articles", true)
}

func (euc *ExampleUsageController) BatchUnpublishArticles(c *gin.Context) {
	if BatchOps == nil {
		BatchOps = NewBatchOperationsController(euc.DB)
	}
	BatchOps.BatchPublish(c, &models.Article{}, "articles", false)
}

// ===== EXAMPLE 8: Get Entity with Standard Response =====
func (euc *ExampleUsageController) GetArticle(c *gin.Context) {
	id := c.Param("id")

	var article models.Article
	if err := euc.DB.Preload("Author").Preload("Category").First(&article, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			Respond.NotFound(c, "Article not found")
			return
		}
		Respond.InternalError(c, "Failed to retrieve article")
		return
	}

	Respond.Success(c, article, "Article retrieved successfully")
}

// ===== EXAMPLE 9: Delete with Audit =====
func (euc *ExampleUsageController) DeleteArticleWithAudit(c *gin.Context) {
	id := c.Param("id")

	var article models.Article
	if err := euc.DB.First(&article, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			Respond.NotFound(c, "Article not found")
			return
		}
		Respond.InternalError(c, "Failed to retrieve article")
		return
	}

	title := article.Title
	articleID := article.ID

	if err := euc.DB.Delete(&article).Error; err != nil {
		Respond.InternalError(c, "Failed to delete article")
		return
	}

	// Log the deletion
	if AuditLogger != nil {
		_ = AuditLogger.LogDelete(c, "Article", articleID, "Article deleted: "+title)
	}

	Respond.NoContent(c)
}

// ===== EXAMPLE 10: Complex Query with Multiple Filters =====
func (euc *ExampleUsageController) SearchArticlesComplex(c *gin.Context) {
	// Start with base query
	query := euc.DB.Model(&models.Article{})

	// Get search term
	searchTerm := QueryParser.GetSearchQuery(c)
	if searchTerm != "" {
		query = QueryParser.ApplySearch(query, searchTerm, "title", "content", "seo_description")
	}

	// Apply boolean filters
	if published := QueryParser.GetBoolQuery(c, "published"); published != nil {
		query = query.Where("published = ?", *published)
	}

	if featured := QueryParser.GetBoolQuery(c, "featured"); featured != nil {
		query = query.Where("featured = ?", *featured)
	}

	// Apply category filter
	if categoryID := c.Query("category_id"); categoryID != "" {
		query = query.Where("category_id = ?", categoryID)
	}

	// Apply date range
	from, to := QueryParser.GetDateRange(c)
	if from != "" {
		query = query.Where("created_at >= ?", from)
	}
	if to != "" {
		query = query.Where("created_at <= ?", to)
	}

	// Apply sorting
	query = QueryParser.ApplySortFromContext(c, query, "created_at", "desc")

	// Execute with pagination
	var articles []models.Article
	meta, err := Paginator.PaginateWithPreload(c, query, &articles, "Author", "Category")
	if err != nil {
		Respond.InternalError(c, "Failed to search articles")
		return
	}

	Respond.SuccessWithMeta(c, articles, meta, "Search completed successfully")
}
