using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using RealCV.Application.Helpers;
using RealCV.Application.Models;

namespace RealCV.Web.Services;

public class PdfReportService : IPdfReportService
{
    /// <summary>
    /// Generates a detailed PDF report for a single CV verification.
    /// </summary>
    public byte[] GenerateSingleReport(string candidateName, VeracityReport report)
    {
        QuestPDF.Settings.License = LicenseType.Community;

        var document = Document.Create(container =>
        {
            container.Page(page =>
            {
                page.Size(PageSizes.A4);
                page.Margin(40);
                page.DefaultTextStyle(x => x.FontSize(10));

                page.Header().Element(c => ComposeSingleReportHeader(c, candidateName, report));
                page.Content().Element(c => ComposeSingleReportContent(c, report));
                page.Footer().Element(ComposeFooter);
            });
        });

        return document.GeneratePdf();
    }

    private void ComposeSingleReportHeader(IContainer container, string candidateName, VeracityReport report)
    {
        var scoreColor = report.OverallScore > ScoreThresholds.High ? Colors.Green.Darken1 :
                        (report.OverallScore >= ScoreThresholds.Medium ? Colors.Orange.Darken1 : Colors.Red.Darken1);

        container.Column(column =>
        {
            column.Item().Row(row =>
            {
                row.RelativeItem().Column(col =>
                {
                    col.Item().Text("RealCV").Bold().FontSize(24).FontColor(Colors.Blue.Darken2);
                    col.Item().Text("CV Verification Report").FontSize(14).FontColor(Colors.Grey.Darken1);
                });
                row.ConstantItem(100).AlignRight().Column(col =>
                {
                    col.Item().AlignRight().Text(report.GeneratedAt.ToString("dd MMM yyyy")).FontSize(10).FontColor(Colors.Grey.Medium);
                    col.Item().AlignRight().Text(report.GeneratedAt.ToString("HH:mm")).FontSize(9).FontColor(Colors.Grey.Medium);
                });
            });

            column.Item().PaddingTop(15).Row(row =>
            {
                row.RelativeItem().Column(col =>
                {
                    col.Item().Text("Candidate: " + candidateName).Bold().FontSize(12);
                });
                row.ConstantItem(120).Border(2).BorderColor(scoreColor).Padding(10).AlignCenter().Column(col =>
                {
                    col.Item().AlignCenter().Text(report.OverallScore.ToString()).Bold().FontSize(28).FontColor(scoreColor);
                    col.Item().AlignCenter().Text("RealCV Score").FontSize(10).FontColor(scoreColor);
                });
            });

            column.Item().PaddingTop(10).LineHorizontal(1).LineColor(Colors.Grey.Lighten2);
        });
    }

    private void ComposeSingleReportContent(IContainer container, VeracityReport report)
    {
        container.PaddingVertical(15).Column(column =>
        {
            // Employment Verification Section
            column.Item().Text("Employment Verification").Bold().FontSize(12).FontColor(Colors.Blue.Darken2);
            column.Item().PaddingTop(10).Table(table =>
            {
                table.ColumnsDefinition(columns =>
                {
                    columns.RelativeColumn(3); // Claimed
                    columns.RelativeColumn(2); // Period
                    columns.RelativeColumn(3); // Matched
                    columns.ConstantColumn(45); // Score
                    columns.ConstantColumn(55); // Status
                });

                table.Header(header =>
                {
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).Text("Claimed Employer").Bold().FontSize(9).FontColor(Colors.White);
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).Text("Period").Bold().FontSize(9).FontColor(Colors.White);
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).Text("Matched Company").Bold().FontSize(9).FontColor(Colors.White);
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).AlignCenter().Text("Match").Bold().FontSize(9).FontColor(Colors.White);
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).AlignCenter().Text("Status").Bold().FontSize(9).FontColor(Colors.White);
                });

                bool alternate = false;
                foreach (var emp in report.EmploymentVerifications)
                {
                    var bgColor = alternate ? Colors.Grey.Lighten4 : Colors.White;
                    var period = emp.ClaimedStartDate.HasValue
                        ? $"{emp.ClaimedStartDate.Value:MMM yyyy} - {(emp.ClaimedEndDate.HasValue ? emp.ClaimedEndDate.Value.ToString("MMM yyyy") : "Present")}"
                        : "Not specified";

                    table.Cell().Background(bgColor).Padding(4).Text(emp.ClaimedCompany).FontSize(9);
                    table.Cell().Background(bgColor).Padding(4).Text(period).FontSize(8);
                    table.Cell().Background(bgColor).Padding(4).Text(emp.MatchedCompanyName ?? "No match").FontSize(9).FontColor(emp.IsVerified ? Colors.Black : Colors.Grey.Medium);
                    table.Cell().Background(bgColor).Padding(4).AlignCenter().Text(emp.MatchScore + "%").FontSize(9);
                    table.Cell().Background(bgColor).Padding(4).AlignCenter().Text(emp.IsVerified ? "Verified" : "Unverified").FontSize(8)
                        .FontColor(emp.IsVerified ? Colors.Green.Darken1 : Colors.Orange.Darken1);

                    alternate = !alternate;
                }
            });

            // Timeline Section
            column.Item().PaddingTop(20).Text("Timeline Analysis").Bold().FontSize(12).FontColor(Colors.Blue.Darken2);
            column.Item().PaddingTop(10).Row(row =>
            {
                row.RelativeItem().Border(1).BorderColor(Colors.Grey.Lighten2).Padding(10).Column(col =>
                {
                    col.Item().Text("Employment Gaps").Bold().FontSize(10);
                    if (report.TimelineAnalysis.Gaps.Count > 0)
                    {
                        foreach (var gap in report.TimelineAnalysis.Gaps)
                        {
                            col.Item().PaddingTop(5).Text($"{gap.StartDate:MMM yyyy} - {gap.EndDate:MMM yyyy} ({gap.Months} months)").FontSize(9);
                        }
                        col.Item().PaddingTop(5).Text($"Total: {report.TimelineAnalysis.TotalGapMonths} months").Bold().FontSize(9).FontColor(Colors.Orange.Darken1);
                    }
                    else
                    {
                        col.Item().PaddingTop(5).Text("No significant gaps detected").FontSize(9).FontColor(Colors.Green.Darken1);
                    }
                });

                row.ConstantItem(15);

                row.RelativeItem().Border(1).BorderColor(Colors.Grey.Lighten2).Padding(10).Column(col =>
                {
                    col.Item().Text("Concurrent Employment").Bold().FontSize(10);
                    if (report.TimelineAnalysis.Overlaps.Count > 0)
                    {
                        foreach (var overlap in report.TimelineAnalysis.Overlaps)
                        {
                            col.Item().PaddingTop(5).Text($"{overlap.Company1} & {overlap.Company2}").FontSize(9);
                            col.Item().Text($"  {overlap.OverlapStart:MMM yyyy} - {overlap.OverlapEnd:MMM yyyy} ({overlap.Months} mo)").FontSize(8).FontColor(Colors.Grey.Darken1);
                        }
                    }
                    else
                    {
                        col.Item().PaddingTop(5).Text("No overlapping positions").FontSize(9).FontColor(Colors.Green.Darken1);
                    }
                });
            });

            // Flags Section
            if (report.Flags.Count > 0)
            {
                column.Item().PaddingTop(20).Text("Flags Raised").Bold().FontSize(12).FontColor(Colors.Blue.Darken2);

                var criticalFlags = report.Flags.Where(f => f.Severity == "Critical").ToList();
                var warningFlags = report.Flags.Where(f => f.Severity == "Warning").ToList();
                var infoFlags = report.Flags.Where(f => f.Severity == "Info").ToList();

                if (criticalFlags.Count > 0)
                {
                    column.Item().PaddingTop(10).Background(Colors.Red.Lighten5).Border(1).BorderColor(Colors.Red.Lighten3).Padding(10).Column(col =>
                    {
                        col.Item().Text("Critical Issues").Bold().FontSize(10).FontColor(Colors.Red.Darken1);
                        foreach (var flag in criticalFlags)
                        {
                            col.Item().PaddingTop(5).Text($"• {flag.Title} ({flag.ScoreImpact} pts)").FontSize(9).Bold();
                            col.Item().Text($"  {flag.Description}").FontSize(8).FontColor(Colors.Grey.Darken1);
                        }
                    });
                }

                if (warningFlags.Count > 0)
                {
                    column.Item().PaddingTop(10).Background(Colors.Orange.Lighten5).Border(1).BorderColor(Colors.Orange.Lighten3).Padding(10).Column(col =>
                    {
                        col.Item().Text("Warnings").Bold().FontSize(10).FontColor(Colors.Orange.Darken1);
                        foreach (var flag in warningFlags)
                        {
                            col.Item().PaddingTop(5).Text($"• {flag.Title} ({flag.ScoreImpact} pts)").FontSize(9).Bold();
                            col.Item().Text($"  {flag.Description}").FontSize(8).FontColor(Colors.Grey.Darken1);
                        }
                    });
                }

                if (infoFlags.Count > 0)
                {
                    column.Item().PaddingTop(10).Background(Colors.Blue.Lighten5).Border(1).BorderColor(Colors.Blue.Lighten3).Padding(10).Column(col =>
                    {
                        col.Item().Text("Information").Bold().FontSize(10).FontColor(Colors.Blue.Darken1);
                        foreach (var flag in infoFlags)
                        {
                            col.Item().PaddingTop(5).Text($"• {flag.Title}").FontSize(9).Bold();
                            col.Item().Text($"  {flag.Description}").FontSize(8).FontColor(Colors.Grey.Darken1);
                        }
                    });
                }
            }
        });
    }

    /// <summary>
    /// Generates a summary PDF report for multiple CV verifications (batch report).
    /// </summary>
    public byte[] GenerateReport(List<PdfReportData> data)
    {
        QuestPDF.Settings.License = LicenseType.Community;

        var document = Document.Create(container =>
        {
            container.Page(page =>
            {
                page.Size(PageSizes.A4);
                page.Margin(40);
                page.DefaultTextStyle(x => x.FontSize(10));

                page.Header().Element(ComposeHeader);
                page.Content().Element(c => ComposeContent(c, data));
                page.Footer().Element(ComposeFooter);
            });
        });

        return document.GeneratePdf();
    }

    private void ComposeHeader(IContainer container)
    {
        container.Column(column =>
        {
            column.Item().Row(row =>
            {
                row.RelativeItem().Column(col =>
                {
                    col.Item().Text("RealCV").Bold().FontSize(24).FontColor(Colors.Blue.Darken2);
                    col.Item().Text("CV Verification Report Summary").FontSize(14).FontColor(Colors.Grey.Darken1);
                });
                row.ConstantItem(100).AlignRight().Text(DateTime.Now.ToString("dd MMM yyyy")).FontSize(10).FontColor(Colors.Grey.Medium);
            });
            column.Item().PaddingTop(10).LineHorizontal(1).LineColor(Colors.Grey.Lighten2);
        });
    }

    private void ComposeContent(IContainer container, List<PdfReportData> data)
    {
        container.PaddingVertical(20).Column(column =>
        {
            column.Item().Text("Summary of " + data.Count + " Verified CVs").Bold().FontSize(12);
            column.Item().PaddingTop(15);

            column.Item().Table(table =>
            {
                table.ColumnsDefinition(columns =>
                {
                    columns.RelativeColumn(3);
                    columns.RelativeColumn(2);
                    columns.ConstantColumn(50);
                    columns.ConstantColumn(45);
                    columns.ConstantColumn(45);
                    columns.ConstantColumn(45);
                    columns.ConstantColumn(45);
                });

                table.Header(header =>
                {
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).Text("Candidate").Bold().FontColor(Colors.White);
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).Text("Date").Bold().FontColor(Colors.White);
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).AlignCenter().Text("Score").Bold().FontColor(Colors.White);
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).AlignCenter().Text("Verified").Bold().FontColor(Colors.White);
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).AlignCenter().Text("Gaps").Bold().FontColor(Colors.White);
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).AlignCenter().Text("Critical").Bold().FontColor(Colors.White);
                    header.Cell().Background(Colors.Blue.Darken2).Padding(5).AlignCenter().Text("Warnings").Bold().FontColor(Colors.White);
                });

                bool alternate = false;
                foreach (var item in data)
                {
                    var bgColor = alternate ? Colors.Grey.Lighten4 : Colors.White;
                    var scoreColor = item.Score > ScoreThresholds.High ? Colors.Green.Darken1 : (item.Score >= ScoreThresholds.Medium ? Colors.Orange.Darken1 : Colors.Red.Darken1);

                    table.Cell().Background(bgColor).Padding(5).Text(item.CandidateName);
                    table.Cell().Background(bgColor).Padding(5).Text(item.UploadDate.ToString("dd MMM yy"));
                    table.Cell().Background(bgColor).Padding(5).AlignCenter().Text(item.Score.ToString()).Bold().FontColor(scoreColor);
                    table.Cell().Background(bgColor).Padding(5).AlignCenter().Text(item.VerifiedEmployers + "/" + (item.VerifiedEmployers + item.UnverifiedEmployers));
                    table.Cell().Background(bgColor).Padding(5).AlignCenter().Text(item.GapMonths + "mo");
                    table.Cell().Background(bgColor).Padding(5).AlignCenter().Text(item.CriticalFlags.ToString()).FontColor(item.CriticalFlags > 0 ? Colors.Red.Darken1 : Colors.Grey.Medium);
                    table.Cell().Background(bgColor).Padding(5).AlignCenter().Text(item.WarningFlags.ToString()).FontColor(item.WarningFlags > 0 ? Colors.Orange.Darken1 : Colors.Grey.Medium);

                    alternate = !alternate;
                }
            });
        });
    }

    private void ComposeFooter(IContainer container)
    {
        container.Column(column =>
        {
            column.Item().LineHorizontal(1).LineColor(Colors.Grey.Lighten2);
            column.Item().PaddingTop(10).Row(row =>
            {
                row.RelativeItem().Text("Generated by RealCV - CV Verification Platform").FontSize(8).FontColor(Colors.Grey.Medium);
                row.RelativeItem().AlignRight().Text(x =>
                {
                    x.Span("Page ").FontSize(8).FontColor(Colors.Grey.Medium);
                    x.CurrentPageNumber().FontSize(8).FontColor(Colors.Grey.Medium);
                    x.Span(" of ").FontSize(8).FontColor(Colors.Grey.Medium);
                    x.TotalPages().FontSize(8).FontColor(Colors.Grey.Medium);
                });
            });
        });
    }
}

public class PdfReportData
{
    public string CandidateName { get; set; } = "";
    public DateTime UploadDate { get; set; }
    public int Score { get; set; }
    public string ScoreLabel { get; set; } = "";
    public int VerifiedEmployers { get; set; }
    public int UnverifiedEmployers { get; set; }
    public int GapMonths { get; set; }
    public int OverlapMonths { get; set; }
    public int CriticalFlags { get; set; }
    public int WarningFlags { get; set; }
}
