/**
 * Calculate the onshore/offshore staffing ratio for a project.
 * "Onshore" = resources in the configured country (default: DE).
 * "Offshore" = everything else (including resources without a country).
 */

export interface ShoringAssignment {
  resourceId: string;
  countryCode: string | null;
  hoursPerDay: number;
  workingDays: number;
}

export interface ShoringCountryBreakdown {
  hours: number;
  pct: number;
  resourceCount: number;
}

export interface ShoringResult {
  totalHours: number;
  onshoreHours: number;
  offshoreHours: number;
  onshoreRatio: number;  // 0-100
  offshoreRatio: number; // 0-100
  threshold: number;
  isAboveThreshold: boolean;
  onshoreCountryCode: string;
  /** Breakdown per country code ("DE" → { hours, pct, resourceCount }) */
  byCountry: Record<string, ShoringCountryBreakdown>;
  /** Resources with no country assigned */
  unknownCount: number;
}

/**
 * @param assignments - All active assignments for a project with their resource's country
 * @param threshold - Max offshore percentage before alert (default 55)
 * @param onshoreCountryCode - Country code considered "onshore" (default "DE")
 */
export function calculateShoringRatio(
  assignments: ShoringAssignment[],
  threshold = 55,
  onshoreCountryCode = "DE",
): ShoringResult {
  if (assignments.length === 0) {
    return {
      totalHours: 0,
      onshoreHours: 0,
      offshoreHours: 0,
      onshoreRatio: 0,
      offshoreRatio: 0,
      threshold,
      isAboveThreshold: false,
      onshoreCountryCode,
      byCountry: {},
      unknownCount: 0,
    };
  }

  const byCountry: Record<string, { hours: number; resources: Set<string> }> = {};
  let totalHours = 0;
  let onshoreHours = 0;
  let unknownCount = 0;
  const unknownResources = new Set<string>();

  for (const a of assignments) {
    const hours = a.hoursPerDay * a.workingDays;
    totalHours += hours;

    const code = a.countryCode?.toUpperCase() ?? "UNKNOWN";

    if (code === "UNKNOWN") {
      if (!unknownResources.has(a.resourceId)) {
        unknownCount++;
        unknownResources.add(a.resourceId);
      }
    }

    if (!byCountry[code]) {
      byCountry[code] = { hours: 0, resources: new Set() };
    }
    byCountry[code].hours += hours;
    byCountry[code].resources.add(a.resourceId);

    if (code === onshoreCountryCode.toUpperCase()) {
      onshoreHours += hours;
    }
  }

  const offshoreHours = totalHours - onshoreHours;
  const offshoreRatio = totalHours > 0 ? Math.round((offshoreHours / totalHours) * 100) : 0;
  const onshoreRatio = totalHours > 0 ? 100 - offshoreRatio : 0;

  const result: Record<string, ShoringCountryBreakdown> = {};
  for (const [code, data] of Object.entries(byCountry)) {
    result[code] = {
      hours: data.hours,
      pct: totalHours > 0 ? Math.round((data.hours / totalHours) * 100) : 0,
      resourceCount: data.resources.size,
    };
  }

  return {
    totalHours,
    onshoreHours,
    offshoreHours,
    onshoreRatio,
    offshoreRatio,
    threshold,
    isAboveThreshold: offshoreRatio >= threshold,
    onshoreCountryCode: onshoreCountryCode.toUpperCase(),
    byCountry: result,
    unknownCount,
  };
}
