using Meezi.Admin.API.Controllers;
using Meezi.Core.Entities;
using Meezi.Core.Enums;
using Meezi.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;

namespace Meezi.Admin.API.Services;

public class AdminWebsiteService(AppDbContext db) : IAdminWebsiteService
{
    // ── Posts ─────────────────────────────────────────────────────────────

    public async Task<object> ListPostsAsync(int page, int limit, bool? published, CancellationToken ct)
    {
        var q = db.WebsiteBlogPosts.AsQueryable();
        if (published.HasValue) q = q.Where(p => p.IsPublished == published.Value);
        var total = await q.CountAsync(ct);
        var posts = await q.OrderByDescending(p => p.CreatedAt)
            .Skip((page - 1) * limit).Take(limit).ToListAsync(ct);
        return new { Posts = posts.Select(MapPost), Total = total, Page = page, Limit = limit };
    }

    public async Task<object?> GetPostAsync(string id, CancellationToken ct)
    {
        var post = await db.WebsiteBlogPosts.FindAsync([id], ct);
        return post is null ? null : MapPost(post);
    }

    public async Task<object> CreatePostAsync(UpsertPostRequest req, CancellationToken ct)
    {
        var post = new WebsiteBlogPost
        {
            Slug        = req.Slug.Trim().ToLowerInvariant(),
            TitleFa     = req.TitleFa,
            TitleEn     = req.TitleEn ?? "",
            ExcerptFa   = req.ExcerptFa ?? "",
            ExcerptEn   = req.ExcerptEn ?? "",
            ContentFa   = req.ContentFa,
            ContentEn   = req.ContentEn ?? "",
            CategoryFa  = req.CategoryFa ?? "",
            CategoryEn  = req.CategoryEn ?? "",
            Author      = req.Author ?? "تیم میزی",
            TagsJson    = req.TagsJson ?? "[]",
            CoverImage  = req.CoverImage,
            IsPublished = req.IsPublished,
            PublishedAt = req.IsPublished ? DateTime.UtcNow : null,
        };
        db.WebsiteBlogPosts.Add(post);
        await db.SaveChangesAsync(ct);
        return MapPost(post);
    }

    public async Task<object?> UpdatePostAsync(string id, UpsertPostRequest req, CancellationToken ct)
    {
        var post = await db.WebsiteBlogPosts.FindAsync([id], ct);
        if (post is null) return null;

        post.Slug        = req.Slug.Trim().ToLowerInvariant();
        post.TitleFa     = req.TitleFa;
        post.TitleEn     = req.TitleEn ?? "";
        post.ExcerptFa   = req.ExcerptFa ?? "";
        post.ExcerptEn   = req.ExcerptEn ?? "";
        post.ContentFa   = req.ContentFa;
        post.ContentEn   = req.ContentEn ?? "";
        post.CategoryFa  = req.CategoryFa ?? "";
        post.CategoryEn  = req.CategoryEn ?? "";
        post.Author      = req.Author ?? post.Author;
        post.TagsJson    = req.TagsJson ?? "[]";
        post.CoverImage  = req.CoverImage;
        if (req.IsPublished && !post.IsPublished) post.PublishedAt = DateTime.UtcNow;
        post.IsPublished = req.IsPublished;

        await db.SaveChangesAsync(ct);
        return MapPost(post);
    }

    public async Task DeletePostAsync(string id, CancellationToken ct)
    {
        var post = await db.WebsiteBlogPosts.FindAsync([id], ct);
        if (post is not null) { post.DeletedAt = DateTime.UtcNow; await db.SaveChangesAsync(ct); }
    }

    public async Task SetPublishedAsync(string id, bool published, CancellationToken ct)
    {
        var post = await db.WebsiteBlogPosts.FindAsync([id], ct);
        if (post is null) return;
        post.IsPublished = published;
        if (published && post.PublishedAt is null) post.PublishedAt = DateTime.UtcNow;
        await db.SaveChangesAsync(ct);
    }

    // ── Comments ──────────────────────────────────────────────────────────

    public async Task<object> ListCommentsAsync(bool? approved, int page, int limit, CancellationToken ct)
    {
        var q = db.WebsiteComments.AsQueryable();
        if (approved.HasValue) q = q.Where(c => c.IsApproved == approved.Value);
        var total = await q.CountAsync(ct);
        var comments = await q.OrderByDescending(c => c.CreatedAt)
            .Skip((page - 1) * limit).Take(limit).ToListAsync(ct);
        return new
        {
            Comments = comments.Select(c => new
            {
                c.Id, c.PostSlug, c.AuthorName, c.AuthorEmail,
                c.Content, c.IsApproved, c.CreatedAt, c.IpAddress,
            }),
            Total = total, Page = page, Limit = limit,
        };
    }

    public async Task SetCommentApprovedAsync(string id, bool approved, CancellationToken ct)
    {
        var c = await db.WebsiteComments.FindAsync([id], ct);
        if (c is null) return;
        c.IsApproved = approved;
        await db.SaveChangesAsync(ct);
    }

    public async Task DeleteCommentAsync(string id, CancellationToken ct)
    {
        var c = await db.WebsiteComments.FindAsync([id], ct);
        if (c is not null) { c.DeletedAt = DateTime.UtcNow; await db.SaveChangesAsync(ct); }
    }

    // ── Demo requests ─────────────────────────────────────────────────────

    public async Task<object> ListDemoRequestsAsync(string? status, int page, int limit, CancellationToken ct)
    {
        var q = db.DemoRequests.AsQueryable();
        if (status is not null && Enum.TryParse<DemoRequestStatus>(status, true, out var s))
            q = q.Where(r => r.Status == s);
        var total = await q.CountAsync(ct);
        var reqs = await q.OrderByDescending(r => r.CreatedAt)
            .Skip((page - 1) * limit).Take(limit).ToListAsync(ct);
        return new
        {
            Requests = reqs.Select(r => new
            {
                r.Id, r.ContactName, r.BusinessName, r.Phone, r.Email,
                r.BranchCount, r.Notes, r.Source, r.AdminNotes,
                Status = r.Status.ToString(), r.ContactedAt, r.CreatedAt,
            }),
            Total = total, Page = page, Limit = limit,
        };
    }

    public async Task UpdateDemoStatusAsync(string id, string status, string? adminNotes, CancellationToken ct)
    {
        var req = await db.DemoRequests.FindAsync([id], ct);
        if (req is null) return;
        if (Enum.TryParse<DemoRequestStatus>(status, true, out var s)) req.Status = s;
        if (adminNotes is not null) req.AdminNotes = adminNotes;
        if (s == DemoRequestStatus.Contacted && req.ContactedAt is null) req.ContactedAt = DateTime.UtcNow;
        await db.SaveChangesAsync(ct);
    }

    // ── Mapper ────────────────────────────────────────────────────────────

    private static object MapPost(WebsiteBlogPost p) => new
    {
        p.Id, p.Slug, p.TitleFa, p.TitleEn, p.ExcerptFa, p.ExcerptEn,
        p.ContentFa, p.ContentEn, p.CategoryFa, p.CategoryEn, p.Author,
        p.TagsJson, p.CoverImage, p.IsPublished, p.PublishedAt, p.ViewCount, p.CreatedAt,
    };
}
