/**
 * Axint Live Activity Generator
 *
 * Turns an `IRLiveActivity` into idiomatic ActivityKit Swift. The
 * emitted shape passes every rule in `swift-validator-live-activities.ts`
 * (AX740–AX749):
 *
 *   - Imports ActivityKit + SwiftUI + WidgetKit
 *   - Emits a `struct <Name>Attributes: ActivityAttributes` with a
 *     nested `ContentState: Codable, Hashable`
 *   - Wraps the whole thing in a `Widget` with `ActivityConfiguration`
 *   - Fills every required Dynamic Island region
 */

import type { IRLiveActivity, IRType, ViewBodyNode } from "./types.js";
import { irTypeToSwift } from "./types.js";
import { escapeSwiftString, generatedFileHeader } from "./generator.js";
import { emitBodyNode } from "./view-body-emitter.js";

export function generateSwiftLiveActivity(activity: IRLiveActivity): string {
  const lines: string[] = [];
  const attrs = `${activity.name}Attributes`;

  lines.push(...generatedFileHeader(`${activity.name}LiveActivity.swift`));
  lines.push(``);
  lines.push(`import ActivityKit`);
  lines.push(`import SwiftUI`);
  lines.push(`import WidgetKit`);
  lines.push(``);

  // Attributes + nested ContentState
  lines.push(`struct ${attrs}: ActivityAttributes {`);
  lines.push(`    public struct ContentState: Codable, Hashable {`);
  for (const field of activity.contentState) {
    lines.push(`        var ${field.name}: ${irTypeToSwift(field.type)}`);
  }
  lines.push(`    }`);
  if (activity.attributes.length > 0) {
    lines.push(``);
    for (const field of activity.attributes) {
      lines.push(`    let ${field.name}: ${irTypeToSwift(field.type)}`);
    }
  }
  lines.push(`}`);
  lines.push(``);

  // Widget wrapping ActivityConfiguration
  lines.push(`struct ${activity.name}LiveActivity: Widget {`);
  lines.push(`    var body: some WidgetConfiguration {`);
  lines.push(`        ActivityConfiguration(for: ${attrs}.self) { context in`);
  for (const node of activity.lockScreen) {
    lines.push(...emitBodyNode(node, 3));
  }
  lines.push(`        } dynamicIsland: { context in`);
  lines.push(`            DynamicIsland {`);
  lines.push(...emitExpandedRegion(activity.dynamicIsland.expanded, 4, ".center"));
  if (activity.dynamicIsland.bottom && activity.dynamicIsland.bottom.length > 0) {
    lines.push(...emitExpandedRegion(activity.dynamicIsland.bottom, 4, ".bottom"));
  }
  lines.push(`            } compactLeading: {`);
  lines.push(...emitBodyGroup(activity.dynamicIsland.compactLeading, 4));
  lines.push(`            } compactTrailing: {`);
  lines.push(...emitBodyGroup(activity.dynamicIsland.compactTrailing, 4));
  lines.push(`            } minimal: {`);
  lines.push(...emitBodyGroup(activity.dynamicIsland.minimal, 4));
  lines.push(`            }`);
  lines.push(`        }`);
  lines.push(`    }`);
  lines.push(`}`);
  lines.push(``);

  // Preview
  lines.push(
    `#Preview("${escapeSwiftString(activity.name)}", as: .content, using: ${attrs}(${previewAttrArgs(activity)})) {`
  );
  lines.push(`    ${activity.name}LiveActivity()`);
  lines.push(`} contentStates: {`);
  lines.push(`    ${attrs}.ContentState(${previewContentStateArgs(activity)})`);
  lines.push(`}`);
  lines.push(``);

  return lines.join("\n");
}

// ─── Internals ──────────────────────────────────────────────────────

function emitExpandedRegion(
  body: ViewBodyNode[],
  depth: number,
  placement: string
): string[] {
  const indent = "    ".repeat(depth);
  const out: string[] = [];
  out.push(`${indent}DynamicIslandExpandedRegion(${placement}) {`);
  out.push(...emitBodyGroup(body, depth + 1));
  out.push(`${indent}}`);
  return out;
}

function emitBodyGroup(body: ViewBodyNode[], depth: number): string[] {
  if (body.length === 0) {
    // ActivityKit refuses empty closures — fall back to EmptyView to stay
    // compilable even when the IR somehow arrives empty.
    const indent = "    ".repeat(depth);
    return [`${indent}EmptyView()`];
  }
  const out: string[] = [];
  for (const node of body) {
    out.push(...emitBodyNode(node, depth));
  }
  return out;
}

function previewAttrArgs(activity: IRLiveActivity): string {
  return activity.attributes
    .map((f) => `${f.name}: ${swiftSampleLiteral(f.type, f.defaultValue)}`)
    .join(", ");
}

function previewContentStateArgs(activity: IRLiveActivity): string {
  return activity.contentState
    .map((f) => `${f.name}: ${swiftSampleLiteral(f.type, f.defaultValue)}`)
    .join(", ");
}

function swiftSampleLiteral(type: IRType, fallback: unknown): string {
  if (fallback !== undefined) return formatLiteral(fallback);
  switch (type.kind) {
    case "primitive":
      switch (type.value) {
        case "string":
          return `""`;
        case "int":
          return `0`;
        case "double":
        case "float":
          return `0.0`;
        case "boolean":
          return `false`;
        case "date":
          return `Date()`;
        case "duration":
          return `.seconds(0)`;
        case "url":
          return `URL(string: "https://example.com")!`;
      }
      return `""`;
    case "array":
      return `[]`;
    case "optional":
      return `nil`;
    default:
      return `""`;
  }
}

function formatLiteral(value: unknown): string {
  if (typeof value === "string") return `"${escapeSwiftString(value)}"`;
  if (typeof value === "number") return String(value);
  if (typeof value === "boolean") return value ? "true" : "false";
  if (value === null) return `nil`;
  return `""`;
}
