using System.ComponentModel.DataAnnotations;
using PowderCoating.Application.DTOs.PrepService;
using PowderCoating.Application.DTOs.Quote;

namespace PowderCoating.Application.DTOs.Job;

public class JobDto
{
    public int Id { get; set; }
    public string JobNumber { get; set; } = string.Empty;
    public int CustomerId { get; set; }
    public string CustomerName { get; set; } = string.Empty;
    public string? CustomerCompanyName { get; set; }
    public string? CustomerContactName { get; set; }
    public int? QuoteId { get; set; }
    public string? QuoteNumber { get; set; }
    public string? AssignedUserId { get; set; }
    public string? AssignedWorkerName { get; set; }
    public string Description { get; set; } = string.Empty;

    // Job Status (from lookup table)
    public int JobStatusId { get; set; }
    public string StatusCode { get; set; } = string.Empty;          // For code logic
    public string StatusDisplayName { get; set; } = string.Empty;   // For UI
    public string StatusColorClass { get; set; } = "secondary";     // For badges
    public string? StatusIconClass { get; set; }                    // For icons
    public int StatusDisplayOrder { get; set; }                     // For comparisons
    public bool StatusIsTerminal { get; set; }                      // For filtering
    public bool StatusIsWIP { get; set; }                           // For stats

    // Job Priority (from lookup table)
    public int JobPriorityId { get; set; }
    public string PriorityCode { get; set; } = string.Empty;
    public string PriorityDisplayName { get; set; } = string.Empty;
    public string PriorityColorClass { get; set; } = "secondary";
    public string? PriorityIconClass { get; set; }
    public int PriorityDisplayOrder { get; set; }

    public DateTime? ScheduledDate { get; set; }
    public DateTime? DueDate { get; set; }
    public DateTime? CompletedDate { get; set; }
    // Oven selection (carried over from quote)
    public int? OvenCostId { get; set; }
    public string? OvenLabel { get; set; }

    public decimal QuotedPrice { get; set; }
    public decimal FinalPrice { get; set; }
    public decimal ShopSuppliesAmount { get; set; }
    public decimal ShopSuppliesPercent { get; set; }
    public bool IsRushJob { get; set; }
    public string DiscountType { get; set; } = "None";
    public decimal DiscountValue { get; set; }
    public string? DiscountReason { get; set; }
    public string? CustomerPO { get; set; }
    public string? ProjectName { get; set; }
    public string? SpecialInstructions { get; set; }
    public string? InternalNotes { get; set; }
    public string? Tags { get; set; }
    public bool RequiresCustomerApproval { get; set; }
    public bool IsCustomerApproved { get; set; }

    public string? CustomerEmail { get; set; }
    public bool CustomerNotifyByEmail { get; set; } = true;
    // Customer SMS opt-in — used for SMS compose modal on job details
    public bool CustomerNotifyBySms { get; set; }
    public string? CustomerMobilePhone { get; set; }

    // Job Completion Details
    public decimal? ActualTimeSpentHours { get; set; }

    // Part intake / receiving
    public DateTime? IntakeDate { get; set; }
    public string? IntakeConditionNotes { get; set; }
    public int? IntakePartCount { get; set; }
    public string? IntakeCheckedByUserId { get; set; }
    public string? IntakeCheckedByName { get; set; }

    // Time tracking
    public List<JobTimeEntryDto> TimeEntries { get; set; } = new();
    public decimal TotalLoggedHours => TimeEntries.Sum(t => t.HoursWorked);

    // Rework
    public bool IsReworkJob { get; set; }
    public int? OriginalJobId { get; set; }
    public string? OriginalJobNumber { get; set; }

    public List<JobItemDto> Items { get; set; } = new();
    public List<PrepServiceDto> PrepServices { get; set; } = new();
    public List<int> PrepServiceIds { get; set; } = new();
    public DateTime CreatedAt { get; set; }
}

public class JobListDto
{
    public int Id { get; set; }
    public string JobNumber { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public string CustomerName { get; set; } = string.Empty;
    public string? AssignedUserId { get; set; }
    public string? AssignedWorkerName { get; set; }

    // Job Status (from lookup table)
    public int JobStatusId { get; set; }
    public string StatusCode { get; set; } = string.Empty;
    public string StatusDisplayName { get; set; } = string.Empty;
    public string StatusColorClass { get; set; } = "secondary";
    public bool StatusIsWIP { get; set; }

    // Job Priority (from lookup table)
    public int JobPriorityId { get; set; }
    public string PriorityCode { get; set; } = string.Empty;
    public string PriorityDisplayName { get; set; } = string.Empty;
    public string PriorityColorClass { get; set; } = "secondary";

    public string? CustomerEmail { get; set; }
    public bool CustomerNotifyByEmail { get; set; } = true;
    public string? CustomerPO { get; set; }
    public string? ProjectName { get; set; }
    public DateTime? ScheduledDate { get; set; }
    public DateTime? DueDate { get; set; }
    public decimal FinalPrice { get; set; }
    public DateTime CreatedAt { get; set; }
    public string? Tags { get; set; }
    public bool IsReworkJob { get; set; }
    public int? OriginalJobId { get; set; }
}

public class CreateJobDto
{
    [Required(ErrorMessage = "Customer is required")]
    [Display(Name = "Customer")]
    public int CustomerId { get; set; }

    [Display(Name = "Quote")]
    public int? QuoteId { get; set; }

    [Display(Name = "Assigned Worker")]
    public string? AssignedUserId { get; set; }

    [Display(Name = "Oven")]
    public int? OvenCostId { get; set; }

    [Display(Name = "Batches")]
    [Range(1, 999)]
    public int OvenBatches { get; set; } = 1;

    [Display(Name = "Cycle Time (min)")]
    public int? OvenCycleMinutes { get; set; }

    [Required(ErrorMessage = "Description is required")]
    [StringLength(2000, ErrorMessage = "Description cannot exceed 2000 characters")]
    [Display(Name = "Description")]
    public string Description { get; set; } = string.Empty;

    [Required(ErrorMessage = "Priority is required")]
    [Display(Name = "Priority")]
    public int JobPriorityId { get; set; }  // FK to lookup table

    [Display(Name = "Scheduled Date")]
    public DateTime? ScheduledDate { get; set; }

    [Display(Name = "Due Date")]
    public DateTime? DueDate { get; set; }

    [Range(0, 9999999.99, ErrorMessage = "Quoted price must be between 0 and 9,999,999.99")]
    [Display(Name = "Quoted Price")]
    public decimal QuotedPrice { get; set; }

    [StringLength(100, ErrorMessage = "Customer PO cannot exceed 100 characters")]
    [Display(Name = "Customer PO")]
    public string? CustomerPO { get; set; }
    public string? ProjectName { get; set; }

    [StringLength(2000, ErrorMessage = "Special instructions cannot exceed 2000 characters")]
    [Display(Name = "Special Instructions")]
    public string? SpecialInstructions { get; set; }

    [StringLength(2000, ErrorMessage = "Internal notes cannot exceed 2000 characters")]
    [Display(Name = "Internal Notes")]
    public string? InternalNotes { get; set; }

    [Display(Name = "Tags")]
    [StringLength(500)]
    public string? Tags { get; set; }

    [Display(Name = "Requires Customer Approval")]
    public bool RequiresCustomerApproval { get; set; }

    [Display(Name = "Rush Job")]
    public bool IsRushJob { get; set; }

    [Display(Name = "Discount Type")]
    public string DiscountType { get; set; } = "None";

    [Range(0, double.MaxValue, ErrorMessage = "Discount value must be 0 or greater")]
    [Display(Name = "Discount Value")]
    public decimal DiscountValue { get; set; }

    [StringLength(500)]
    [Display(Name = "Discount Reason")]
    public string? DiscountReason { get; set; }

    public List<CreateQuoteItemDto> JobItems { get; set; } = new();
    public List<int> PrepServiceIds { get; set; } = new();
}

public class UpdateJobDto
{
    [Required]
    public int Id { get; set; }

    [Required(ErrorMessage = "Customer is required")]
    [Display(Name = "Customer")]
    public int CustomerId { get; set; }

    [Display(Name = "Quote")]
    public int? QuoteId { get; set; }

    [Display(Name = "Assigned Worker")]
    public string? AssignedUserId { get; set; }

    [Display(Name = "Oven")]
    public int? OvenCostId { get; set; }

    [Display(Name = "Batches")]
    [Range(1, 999)]
    public int OvenBatches { get; set; } = 1;

    [Display(Name = "Cycle Time (min)")]
    public int? OvenCycleMinutes { get; set; }

    [Required(ErrorMessage = "Description is required")]
    [StringLength(2000, ErrorMessage = "Description cannot exceed 2000 characters")]
    [Display(Name = "Description")]
    public string Description { get; set; } = string.Empty;

    [Required(ErrorMessage = "Status is required")]
    [Display(Name = "Status")]
    public int JobStatusId { get; set; }    // FK to lookup table

    [Required(ErrorMessage = "Priority is required")]
    [Display(Name = "Priority")]
    public int JobPriorityId { get; set; }  // FK to lookup table

    [Display(Name = "Scheduled Date")]
    public DateTime? ScheduledDate { get; set; }

    [Display(Name = "Due Date")]
    public DateTime? DueDate { get; set; }

    [Range(0, 9999999.99, ErrorMessage = "Quoted price must be between 0 and 9,999,999.99")]
    [Display(Name = "Quoted Price")]
    public decimal QuotedPrice { get; set; }

    [StringLength(100, ErrorMessage = "Customer PO cannot exceed 100 characters")]
    [Display(Name = "Customer PO")]
    public string? CustomerPO { get; set; }
    public string? ProjectName { get; set; }

    [StringLength(2000, ErrorMessage = "Special instructions cannot exceed 2000 characters")]
    [Display(Name = "Special Instructions")]
    public string? SpecialInstructions { get; set; }

    [StringLength(2000, ErrorMessage = "Internal notes cannot exceed 2000 characters")]
    [Display(Name = "Internal Notes")]
    public string? InternalNotes { get; set; }

    [Display(Name = "Tags")]
    [StringLength(500)]
    public string? Tags { get; set; }

    [Display(Name = "Requires Customer Approval")]
    public bool RequiresCustomerApproval { get; set; }

    [Display(Name = "Rush Job")]
    public bool IsRushJob { get; set; }

    [Display(Name = "Discount Type")]
    public string DiscountType { get; set; } = "None";

    [Range(0, double.MaxValue, ErrorMessage = "Discount value must be 0 or greater")]
    [Display(Name = "Discount Value")]
    public decimal DiscountValue { get; set; }

    [StringLength(500)]
    [Display(Name = "Discount Reason")]
    public string? DiscountReason { get; set; }

    public List<CreateQuoteItemDto> JobItems { get; set; } = new();
    public List<int> PrepServiceIds { get; set; } = new();

    [Display(Name = "Notify customer of status change via email")]
    public bool SendEmailOnStatusChange { get; set; } = false;
}

public class UpdateJobItemDto
{
    public int Id { get; set; }
    public string Description { get; set; } = string.Empty;
    public decimal Quantity { get; set; }
    public string? ColorName { get; set; }
    public string? ColorCode { get; set; }
    public decimal? SurfaceArea { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal TotalPrice { get; set; }
    public bool RequiresSandblasting { get; set; }
    public bool RequiresMasking { get; set; }
    public int EstimatedMinutes { get; set; }
    public string? Notes { get; set; }
}

public class JobItemDto
{
    public int Id { get; set; }
    public string Description { get; set; } = string.Empty;
    public decimal Quantity { get; set; }
    public string? ColorName { get; set; }
    public string? ColorCode { get; set; }
    public string? Finish { get; set; }
    public decimal? SurfaceArea { get; set; }
    public decimal SurfaceAreaSqFt { get; set; }
    public int EstimatedMinutes { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal TotalPrice { get; set; }
    public decimal LaborCost { get; set; }
    public bool RequiresSandblasting { get; set; }
    public bool RequiresMasking { get; set; }
    public string? Notes { get; set; }
    public int? CatalogItemId { get; set; }
    public bool IsGenericItem { get; set; }
    public bool IsLaborItem { get; set; }
    public bool IsSalesItem { get; set; }
    public bool IsAiItem { get; set; }
    public string? Sku { get; set; }
    public bool IsCustomFormulaItem { get; set; }
    public int? CustomItemTemplateId { get; set; }
    public string? FormulaFieldValuesJson { get; set; }
    public List<JobItemCoatDto> Coats { get; set; } = new();
    public List<JobItemPrepServiceDto> PrepServices { get; set; } = new();
}

public class JobItemPrepServiceDto
{
    public int PrepServiceId { get; set; }
    public string? PrepServiceName { get; set; }
    public int EstimatedMinutes { get; set; }
    /// <summary>Blast setup selected in wizard for this sandblasting prep service.</summary>
    public int? BlastSetupId { get; set; }
}

public class CreateJobItemDto
{
    public string Description { get; set; } = string.Empty;
    public decimal Quantity { get; set; }
    public string? ColorName { get; set; }
    public string? ColorCode { get; set; }
    public string? Finish { get; set; }
    public decimal UnitPrice { get; set; }
    public bool RequiresSandblasting { get; set; }
    public bool RequiresMasking { get; set; }
    public int EstimatedMinutes { get; set; }
    public string? Notes { get; set; }
}

// DTO for Shop Floor Display
public class ShopFloorJobDto
{
    public int Id { get; set; }
    public string JobNumber { get; set; } = string.Empty;
    public string CustomerName { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;

    // Job Status (from lookup table)
    public int JobStatusId { get; set; }
    public string StatusCode { get; set; } = string.Empty;
    public string StatusDisplayName { get; set; } = string.Empty;
    public string StatusColorClass { get; set; } = "secondary";

    // Job Priority (from lookup table)
    public int JobPriorityId { get; set; }
    public string PriorityCode { get; set; } = string.Empty;
    public string PriorityDisplayName { get; set; } = string.Empty;
    public string PriorityColorClass { get; set; } = "secondary";

    public string? AssignedWorkerName { get; set; }
    public DateTime? ScheduledDate { get; set; }
    public DateTime? DueDate { get; set; }
    public int ItemCount { get; set; }
    public List<string> NextSteps { get; set; } = new();
}

// DTO for Job Item Coat (multi-coat support)
public class JobItemCoatDto
{
    public int Id { get; set; }
    public int JobItemId { get; set; }
    public string CoatName { get; set; } = string.Empty;
    public int Sequence { get; set; }
    public int? InventoryItemId { get; set; }
    public string? ColorName { get; set; }
    public int? VendorId { get; set; }
    public string? VendorName { get; set; }
    public string? ColorCode { get; set; }
    public string? Finish { get; set; }
    public decimal CoverageSqFtPerLb { get; set; }
    public decimal TransferEfficiency { get; set; }
    public decimal? PowderCostPerLb { get; set; }
    public decimal? PowderToOrder { get; set; }
    public decimal? ActualPowderUsedLbs { get; set; }  // Filled during job completion
    public bool NoExtraLayerCharge { get; set; }
    public string? Notes { get; set; }
}

// DTO for completing a job
public class CompleteJobDto
{
    public int JobId { get; set; }
    public decimal? ActualTimeSpentHours { get; set; }
    public List<JobPowderUsageDto> PowderUsages { get; set; } = new();
    public bool SendEmailToCustomer { get; set; } = false;
}

// DTO for the Admin/Manager compose-before-send SMS endpoint
public class SendJobSmsRequest
{
    public int JobId { get; set; }
    public string Message { get; set; } = string.Empty;
}

// DTO for tracking actual powder usage per inventory item (color) for the whole job
public class JobPowderUsageDto
{
    public int InventoryItemId { get; set; }
    public decimal? ActualPowderUsedLbs { get; set; }
}

// ── Time Tracking DTOs ────────────────────────────────────────────────────────

public class JobTimeEntryDto
{
    public int Id { get; set; }
    public int JobId { get; set; }
    public string? UserId { get; set; }
    public string WorkerName { get; set; } = string.Empty;
    public DateTime WorkDate { get; set; }
    public decimal HoursWorked { get; set; }
    public string? Stage { get; set; }
    public string? Notes { get; set; }
    public DateTime CreatedAt { get; set; }
}

public class CreateJobTimeEntryDto
{
    public int JobId { get; set; }
    public string UserId { get; set; } = string.Empty;
    public DateTime WorkDate { get; set; }
    public decimal HoursWorked { get; set; }
    public string? Stage { get; set; }
    public string? Notes { get; set; }
}

public class UpdateJobTimeEntryDto
{
    public int Id { get; set; }
    public string UserId { get; set; } = string.Empty;
    public DateTime WorkDate { get; set; }
    public decimal HoursWorked { get; set; }
    public string? Stage { get; set; }
    public string? Notes { get; set; }
}

// ── Rework / Warranty DTOs ────────────────────────────────────────────────────

public class ReworkRecordDto
{
    public int Id { get; set; }
    public int JobId { get; set; }
    public int? JobItemId { get; set; }
    public string? JobItemDescription { get; set; }
    public int? ReworkJobId { get; set; }
    public string? ReworkJobNumber { get; set; }

    public PowderCoating.Core.Enums.ReworkType ReworkType { get; set; }
    public string ReworkTypeDisplay { get; set; } = string.Empty;
    public PowderCoating.Core.Enums.ReworkReason Reason { get; set; }
    public string ReasonDisplay { get; set; } = string.Empty;
    public string DefectDescription { get; set; } = string.Empty;

    public PowderCoating.Core.Enums.ReworkDiscoveredBy DiscoveredBy { get; set; }
    public string DiscoveredByDisplay { get; set; } = string.Empty;
    public DateTime DiscoveredDate { get; set; }
    public string? ReportedByName { get; set; }

    public decimal EstimatedReworkCost { get; set; }
    public decimal ActualReworkCost { get; set; }
    public bool IsBillableToCustomer { get; set; }
    public string? BillingNotes { get; set; }
    public PowderCoating.Core.Enums.ReworkPricingType? ReworkPricingType { get; set; }

    public PowderCoating.Core.Enums.ReworkStatus Status { get; set; }
    public string StatusDisplay { get; set; } = string.Empty;
    public string StatusColorClass { get; set; } = "secondary";
    public PowderCoating.Core.Enums.ReworkResolution? Resolution { get; set; }
    public string? ResolutionDisplay { get; set; }
    public DateTime? ResolvedDate { get; set; }
    public string? ResolutionNotes { get; set; }

    public DateTime CreatedAt { get; set; }
}

public class CreateReworkRecordDto
{
    public int JobId { get; set; }
    public int? JobItemId { get; set; }
    public PowderCoating.Core.Enums.ReworkType ReworkType { get; set; }
    public PowderCoating.Core.Enums.ReworkReason Reason { get; set; }
    public string DefectDescription { get; set; } = string.Empty;
    public PowderCoating.Core.Enums.ReworkDiscoveredBy DiscoveredBy { get; set; }
    public DateTime DiscoveredDate { get; set; } = DateTime.Today;
    public string? ReportedByName { get; set; }
    public decimal EstimatedReworkCost { get; set; }
    public bool IsBillableToCustomer { get; set; }
    public string? BillingNotes { get; set; }

    // Rework job creation (opt-in)
    public bool CreateReworkJob { get; set; }
    public List<int>? ReworkJobItemIds { get; set; }  // null = not creating a job
    public PowderCoating.Core.Enums.ReworkPricingType? ReworkPricingType { get; set; }
}

public class UpdateReworkRecordDto
{
    public int Id { get; set; }
    public PowderCoating.Core.Enums.ReworkStatus Status { get; set; }
    public PowderCoating.Core.Enums.ReworkResolution? Resolution { get; set; }
    public decimal ActualReworkCost { get; set; }
    public bool IsBillableToCustomer { get; set; }
    public string? BillingNotes { get; set; }
    public DateTime? ResolvedDate { get; set; }
    public string? ResolutionNotes { get; set; }
    public int? ReworkJobId { get; set; }
}

// ViewModel for the Edit Items wizard page
public class JobEditItemsViewModel
{
    public int JobId { get; set; }
    public string JobNumber { get; set; } = string.Empty;
    public int? CustomerId { get; set; }
    public decimal TaxPercent { get; set; }
    public int? OvenCostId { get; set; }
    public int OvenBatches { get; set; } = 1;
    public int? OvenCycleMinutes { get; set; }
    public List<CreateQuoteItemDto> JobItems { get; set; } = new();
}

// DTO for the part intake / receiving form
public class IntakeJobDto
{
    [Required]
    public int JobId { get; set; }

    [Display(Name = "Actual Part Count")]
    [Range(0, 10000, ErrorMessage = "Part count must be between 0 and 10,000")]
    public int? ActualPartCount { get; set; }

    [StringLength(2000, ErrorMessage = "Condition notes cannot exceed 2000 characters")]
    [Display(Name = "Condition Notes")]
    public string? ConditionNotes { get; set; }

    [Display(Name = "Advance status to In Preparation")]
    public bool AdvanceToInPreparation { get; set; } = true;
}
