/**
 * Live Tracking Feature - Pure Data Transformation Functions
 * No React, no hooks, no side effects. All business logic lives here.
 */

import type {
  HubspotDeal,
  ClassifiedDeal,
  DisplayStage,
  ProjectProgressData,
  ProjectData,
  LiveTrackerProps,

  DampMouldRiskData,
  FunnelStage,
} from "./types";

import {
  STAGE_ORDER,
  MAJOR_CONDITION_STAGE_ID,
  SUCCESSFUL_SURVEY_OUTCOMES,
} from "./types";

// Terminal stages that exit the pipeline by design — excluded from funnel
// counts and stage-progress denominators.
const STAGES_EXCLUDED_FROM_PIPELINE: ReadonlySet<DisplayStage> = new Set<DisplayStage>([
  "Queries",
  "Removed from Bookings",
  "Removed from Program",
]);

// -----------------------------------------------------------------------
// Stage ID -> raw label mapping
// -----------------------------------------------------------------------
const STAGE_ID_MAP: Record<string, string> = {
  "1617223910": "Scope & Planning", //[Ops] Backlog
  "3583836399": "Scope & Planning", //[Ops] Route Planning
  "3589581001": "Booking in Progress", // [Bookings] Ready for Bookings Team
  "3569878239": "Booking in Progress", //[Bookings] Send initial booking SMS
  "1617223911": "Booking in Progress", // [Bookings] Send Email
  "1984184569": "Booking in Progress", // [Bookings] Phone booking
  "3569572028": "Booking in Progress", // [Bookings] Preferences received from Tenant
  "3570936026": "Booking in Progress", // [Bookings] Send Confirmation Comms
  "3680650446": "Booking in Progress", //[Bookings] Manual Confirmation Comms Required
  "2663668937": "Queries", //[Bookings/Sales] Booking issues - needs HA support
  "1984401629": "Queries", //[Bookings/Ops/Sales] No Contact Details - Ready for Route
  "1617223912": "Assessment in Progress", //[Ops]  Ready for Assignment to Route
  "1617223913": "Assessment in Progress", //[Ops] Survey in Progress
  "2558220518": "Assessment in Progress", // [Ops] Not attempted - needs reallocation
  "3474594026": "Booking in Progress", //[Ops/Bookings] Rebooked - Needs updating
  "3206388924": "Assessment in Progress", //[Ops] Surveyed - Pending Upload from Surveyor
  "1617223915": "Queries", //[Ops] No Access - Need Sign Off
  "1617223917": "Queries", //[Ops] No Access - No Revisit
  "1887735998": "Queries", //[Ops] Not Viable
  "3061261536": "Queries", //[Sales/Tech] Major condition issue
  "3948185842": "AFTER_ASSESSMENT", //[Admin] Admin to check all paperwork for external comms
  "1617223914": "AFTER_ASSESSMENT", // [Ops] Surveyed in Pashub, Transit Job to Co-ordination
  "1617223916": "Queries", // [Ops] Properties to Review Manually
  "2628341989": "Assessment in Progress", //[Ops] Assessment needs correction
  "3441170637": "AFTER_ASSESSMENT", //[Ops] Awaiting PV Design
  "2628233422": "AFTER_ASSESSMENT", //[Coordination] Ready for coordination
  "1887735999": "AFTER_ASSESSMENT", //[Ops] Needs HA Works
  "1960060104": "Queries", //[Ops] HA Informed
  "1960060105": "Queries", //[Ops] HA Works Scheduled
  "1960060106": "AFTER_ASSESSMENT", //[Ops] HA Works Complete
  "2769407184": "Queries", //[Ops] Talk to client, Needs Heating Upgrade (Pre EPR C)
  "2702650617": "AFTER_ASSESSMENT", //[Design] Ready for Design
  "2473886962": "AFTER_ASSESSMENT", //[Design] Design in progress
  "1668803774": "AFTER_ASSESSMENT", //[Ops] post-ERF / completed coordination stage
};

// -----------------------------------------------------------------------
// After-assessment sub-classification
// Resolves AFTER_ASSESSMENT deals based on coordinationStatus + designStatus
// -----------------------------------------------------------------------
function resolveAfterAssessmentStage(
  coordinationStatus: string | null,
  designStatus: string | null
): "Coordination in Progress" | "Design in Progress" | "POST_DESIGN" | "Queries" {
  const coord = coordinationStatus?.toUpperCase() ?? "";
  const design = designStatus?.toUpperCase() ?? "";

  // RA ISSUE always -> Queries
  if (coord === "RA ISSUE") return "Queries";

  // V1/V2/V3 IOE/MTP COMPLETE pattern
  if (
    coord.includes("(V1) IOE/MTP COMPLETE") ||
    coord.includes("(V2) IOE/MTP COMPLETE") ||
    coord.includes("(V3) IOE/MTP COMPLETE")
  ) {
    return design === "UPLOADED" ? "POST_DESIGN" : "Design in Progress";
  }

  // Default for AFTER_ASSESSMENT
  return "Coordination in Progress";
}

// -----------------------------------------------------------------------
// Post-design sub-classification
// Called when design is UPLOADED — resolves install / lodgement / completed
// -----------------------------------------------------------------------
function resolvePostDesignStage(deal: HubspotDeal): DisplayStage {
  if (deal.fullLodgementDate) return "Project Complete";
  if (deal.measuresLodgementDate) return "At Post Survey";
  if (deal.lodgementStatus) return "At Lodgement";
  if (deal.actualMeasuresInstalled || deal.installerHandover) return "Installation Complete";
  return "Installation in Progress";
}

// -----------------------------------------------------------------------
// Resolve display stage for a single deal
// Maps dealstage ID + coordination/design/install status -> DisplayStage
// -----------------------------------------------------------------------
export function resolveDisplayStage(deal: HubspotDeal): DisplayStage {
  if (deal.batch === "Removed from Program") {
    return "Removed from Program";
  }

  if (
    deal.bookingStatus === "Do Not Book" &&
    !(deal.outcome && SUCCESSFUL_SURVEY_OUTCOMES.has(deal.outcome))
  ) {
    return "Removed from Bookings";
  }

  const raw = STAGE_ID_MAP[deal.dealstage ?? ""] ?? "AFTER_ASSESSMENT";

  if (raw === "AFTER_ASSESSMENT") {
    const afterAssessment = resolveAfterAssessmentStage(
      deal.coordinationStatus,
      deal.designStatus
    );

    if (afterAssessment === "POST_DESIGN") {
      return resolvePostDesignStage(deal);
    }

    return afterAssessment;
  }

  // RA ISSUE override can apply to other stages too
  if (raw === "Scope & Planning" || raw === "Assessment in Progress") {
    if (deal.coordinationStatus?.toUpperCase() === "RA ISSUE") {
      return "Queries";
    }
  }

  return raw as DisplayStage;
}

// -----------------------------------------------------------------------
// Classify all deals in a list
// Adds displayStage to each deal
// -----------------------------------------------------------------------
export function classifyDeals(deals: HubspotDeal[]): ClassifiedDeal[] {
  return deals.map((deal) => ({
    ...deal,
    displayStage: resolveDisplayStage(deal),
  }));
}

// -----------------------------------------------------------------------
// Compute damp & mould risk — survey vs coordination stage comparison
// -----------------------------------------------------------------------
function isCoordinatorFlagged(d: ClassifiedDeal): boolean {
  const growthIsYes = d.dampMouldFlag?.trim().toLowerCase() === "yes";
  const hasComment = !!d.dampMouldAndRepairComments?.trim();
  return growthIsYes || hasComment;
}

export function computeDampMouldRisk(deals: ClassifiedDeal[]): DampMouldRiskData {
  const surveyFlagDeals = deals.filter((d) => !!d.majorConditionIssuePhotosS3);
  const coordinatorFlagDeals = deals.filter(isCoordinatorFlagged);
  const bothFlaggedCount = surveyFlagDeals.filter(isCoordinatorFlagged).length;

  return {
    surveyFlagCount: surveyFlagDeals.length,
    coordinatorFlagCount: coordinatorFlagDeals.length,
    bothFlaggedCount,
    totalDeals: deals.length,
    surveyFlagDeals,
    coordinatorFlagDeals,
  };
}

// -----------------------------------------------------------------------
// Compute pipeline funnel — dual counts (current snapshot + cumulative)
// -----------------------------------------------------------------------
export function computeFunnelStages(deals: ClassifiedDeal[]): FunnelStage[] {
  const nonQueryDeals = deals.filter((d) => !STAGES_EXCLUDED_FROM_PIPELINE.has(d.displayStage));
  const total = nonQueryDeals.length;

  return STAGE_ORDER.map((stage) => {
    const stageIndex = STAGE_ORDER.indexOf(stage);

    const currentCount = nonQueryDeals.filter(
      (d) => d.displayStage === stage
    ).length;

    const cumulativeCount = nonQueryDeals.filter(
      (d) => STAGE_ORDER.indexOf(d.displayStage) >= stageIndex
    ).length;

    return {
      stage,
      currentCount,
      currentPct: total > 0 ? (currentCount / total) * 100 : 0,
      cumulativeCount,
      cumulativePct: total > 0 ? (cumulativeCount / total) * 100 : 0,
    };
  });
}

// -----------------------------------------------------------------------
// Compute all ProjectProgressData for a set of already-classified deals
// -----------------------------------------------------------------------
export function computeProjectProgress(
  deals: ClassifiedDeal[]
): ProjectProgressData {
  const queriesDeals = deals.filter((d) => d.displayStage === "Queries");
  const nonQueryDeals = deals.filter((d) => !STAGES_EXCLUDED_FROM_PIPELINE.has(d.displayStage));
  const nonQueryTotal = nonQueryDeals.length;

  // Stage counts/percentages (queries excluded from percentage calculation)
  const stageBuckets: Record<string, ClassifiedDeal[]> = {};
  for (const deal of nonQueryDeals) {
    (stageBuckets[deal.displayStage] ??= []).push(deal);
  }

  const stageProgress = STAGE_ORDER.filter((s) => !STAGES_EXCLUDED_FROM_PIPELINE.has(s)).map(
    (stage) => {
      const stageDeals = stageBuckets[stage] ?? [];
      return {
        stage,
        count: stageDeals.length,
        percentage:
          nonQueryTotal > 0 ? (stageDeals.length / nonQueryTotal) * 100 : 0,
        deals: stageDeals,
      };
    }
  );

  const completedDeals = stageBuckets["Project Complete"] ?? [];
  const completedCount = completedDeals.length;
  const completedPercentage =
    nonQueryTotal > 0 ? (completedCount / nonQueryTotal) * 100 : 0;

  const totalDeals = deals.length;

  return {
    stageProgress,
    queriesDeals,
    completedDeals,
    completedCount,
    completedPercentage,
    nonQueryTotal,
    totalDeals,
    dampMouldRisk: computeDampMouldRisk(deals),
    funnelStages: computeFunnelStages(deals),
  };
}

// -----------------------------------------------------------------------
// Top-level function called by page.tsx
// Orchestrates all transformations: classify, group by project, compute stats
// -----------------------------------------------------------------------
export function computeLiveTrackerData(
  rawDeals: HubspotDeal[]
): Omit<LiveTrackerProps, "docStatusMap" | "userCapability" | "approvalsByDeal" | "instructedMeasuresByDeal" | "removalStatusByDeal" | "portfolioId" | "userRole" | "userEmail"> {
  // Classify all deals (add displayStage field)
  const classified = classifyDeals(rawDeals);

  // Filter for major condition deals (Awaab's Law)
  const majorConditionDeals = classified.filter(
    (d) => d.dealstage === MAJOR_CONDITION_STAGE_ID
  );

  // Group deals by projectCode
  const grouped: Record<string, ClassifiedDeal[]> = {};
  for (const deal of classified) {
    const key = deal.projectCode ?? "Unknown Project";
    (grouped[key] ??= []).push(deal);
  }

  // For each project group, compute progress data
  const projects: ProjectData[] = Object.entries(grouped).map(
    ([projectCode, deals]) => ({
      projectCode,
      progress: computeProjectProgress(deals),
      allDeals: deals,
    })
  );

  // When there are multiple project codes, prepend a synthetic "All Projects" entry
  if (projects.length > 1) {
    projects.unshift({
      projectCode: "__ALL__",
      progress: computeProjectProgress(classified),
      allDeals: classified,
    });
  }

  return {
    projects,
    totalDeals: classified.length,
    majorConditionDeals,
  };
}
