import type { TguPlan, TguPlatform } from "../../model/tguTypes";
import type { TguPlanUi, TguPlatformUi, TimelineRange, TimelineRow } from "../../model/timelineTypes";

const PROBLEM_STATUSES = new Set(["REJECTED", "START_AMBIGUOUS"]);

const OPERATIONAL_STATUS = "OPERATIONAL";

/** На морде показываем только эксплуатируемые КА — с остальными мы не работаем. */
export function isOperationalPlatform(platform: TguPlatform): boolean {
  return (platform.status ?? "").trim().toUpperCase() === OPERATIONAL_STATUS;
}

/** norad-id эксплуатируемых КА; planId.spacecraftId сопоставляется именно с norad-id. */
export function operationalSpacecraftIds(platforms: TguPlatform[]): Set<string> {
  const ids = new Set<string>();
  for (const platform of platforms) {
    if (platform.noradId !== null && platform.noradId !== undefined) {
      ids.add(String(platform.noradId));
    }
  }
  return ids;
}

export function mapPlans(plans: TguPlan[], platforms: TguPlatform[]): TguPlanUi[] {
  const platformByNorad = buildPlatformByNorad(platforms);

  return plans
    .map((plan) => {
      const startMs = new Date(plan.startTime).getTime();
      const endMs = new Date(plan.endTime).getTime();
      const platform = platformByNorad.get(plan.spacecraftId);
      return {
        ...plan,
        startMs,
        endMs,
        platform: platform ? toPlatformUi(plan.spacecraftId, platform, 0, false) : undefined
      };
    })
    .filter((plan) => Number.isFinite(plan.startMs) && Number.isFinite(plan.endMs));
}

export function buildPlatformsForInterval(
  platforms: TguPlatform[],
  plans: TguPlanUi[],
  range: TimelineRange
): TguPlatformUi[] {
  const intervalPlans = filterPlansByRange(plans, range);
  const platformByNorad = buildPlatformByNorad(platforms);
  const planStats = new Map<string, { count: number; hasProblemStatus: boolean }>();

  for (const plan of intervalPlans) {
    const stats = planStats.get(plan.spacecraftId) ?? { count: 0, hasProblemStatus: false };
    stats.count += 1;
    stats.hasProblemStatus = stats.hasProblemStatus || PROBLEM_STATUSES.has(plan.status);
    planStats.set(plan.spacecraftId, stats);
  }

  const platformItems = Array.from(platformByNorad.entries()).map(([spacecraftId, platform]) => {
    const stats = planStats.get(spacecraftId) ?? { count: 0, hasProblemStatus: false };
    return toPlatformUi(spacecraftId, platform, stats.count, stats.hasProblemStatus);
  });

  const knownSpacecraft = new Set(platformItems.map((platform) => platform.spacecraftId));
  for (const [spacecraftId, stats] of planStats.entries()) {
    if (!knownSpacecraft.has(spacecraftId)) {
      platformItems.push({
        spacecraftId,
        noradId: spacecraftId,
        planCount: stats.count,
        hasProblemStatus: stats.hasProblemStatus
      });
    }
  }

  return platformItems.sort((a, b) => platformLabel(a).localeCompare(platformLabel(b), "ru"));
}

export function buildTimelineRows(
  plans: TguPlanUi[],
  platforms: TguPlatformUi[],
  range: TimelineRange,
  selectedSpacecraftId?: string
): TimelineRow[] {
  const platformBySpacecraft = new Map(platforms.map((platform) => [platform.spacecraftId, platform]));
  const rowsBySpacecraft = new Map<string, TimelineRow>();

  for (const plan of filterPlansByRange(plans, range)) {
    if (selectedSpacecraftId && plan.spacecraftId !== selectedSpacecraftId) {
      continue;
    }

    const row =
      rowsBySpacecraft.get(plan.spacecraftId) ??
      {
        spacecraftId: plan.spacecraftId,
        platform: platformBySpacecraft.get(plan.spacecraftId),
        plans: []
      };

    row.plans.push(plan);
    rowsBySpacecraft.set(plan.spacecraftId, row);
  }

  for (const platform of platforms) {
    if (selectedSpacecraftId && platform.spacecraftId !== selectedSpacecraftId) {
      continue;
    }
    if (!rowsBySpacecraft.has(platform.spacecraftId) && platform.planCount > 0) {
      rowsBySpacecraft.set(platform.spacecraftId, {
        spacecraftId: platform.spacecraftId,
        platform,
        plans: []
      });
    }
  }

  return Array.from(rowsBySpacecraft.values())
    .map((row) => ({
      ...row,
      platform: row.platform ?? platformBySpacecraft.get(row.spacecraftId),
      plans: [...row.plans].sort((a, b) => a.startMs - b.startMs)
    }))
    .sort((a, b) => platformLabel(a.platform, a.spacecraftId).localeCompare(platformLabel(b.platform, b.spacecraftId), "ru"));
}

export function filterPlatforms(platforms: TguPlatformUi[], query: string): TguPlatformUi[] {
  const normalized = query.trim().toLowerCase();
  if (!normalized) return platforms;

  return platforms.filter((platform) => {
    const searchText = [
      platform.name,
      platform.noradId,
      platform.spacecraftId,
      platform.mission,
      platform.status
    ]
      .filter(Boolean)
      .join(" ")
      .toLowerCase();

    return searchText.includes(normalized);
  });
}

export function filterPlansByRange(plans: TguPlanUi[], range: TimelineRange): TguPlanUi[] {
  return plans.filter((plan) => plan.endMs >= range.fromMs && plan.startMs <= range.toMs);
}

export function platformLabel(platform?: TguPlatformUi, fallback?: string): string {
  return platform?.name || platform?.noradId || fallback || platform?.spacecraftId || "КА";
}

function buildPlatformByNorad(platforms: TguPlatform[]): Map<string, TguPlatform> {
  const result = new Map<string, TguPlatform>();
  for (const platform of platforms) {
    if (platform.noradId !== null && platform.noradId !== undefined) {
      result.set(String(platform.noradId), platform);
    }
  }
  return result;
}

function toPlatformUi(
  spacecraftId: string,
  platform: TguPlatform,
  planCount: number,
  hasProblemStatus: boolean
): TguPlatformUi {
  return {
    spacecraftId,
    name: platform.name ?? undefined,
    noradId: platform.noradId === null || platform.noradId === undefined ? undefined : String(platform.noradId),
    status: platform.status ?? undefined,
    mission: platform.mission ?? undefined,
    planCount,
    hasProblemStatus,
    platform
  };
}
