import { Component, OnInit, computed, inject, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Router, RouterLink } from '@angular/router';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import { switchMap } from 'rxjs';
import { DietGeneratorService } from '../../core/services/diet-generator.service';
import {
  DEFAULT_DIET_PROFILE,
  DietGeneratorDraftMeal,
  DietGeneratorSession,
  DietUserProfile,
} from '../../core/models/generator.models';
import { MEAL_CATEGORY_I18N_KEYS, MealCategory, RecipeDetail } from '../../core/models/recipe.models';
import { RecipeDetailViewComponent } from '../recipes/recipe-detail-view.component';
import { extractApiError } from '../../core/utils/api-error.util';

type Step = 'profile' | 'macros' | 'plan' | 'done';

@Component({
  selector: 'app-diet-generator',
  standalone: true,
  imports: [FormsModule, RouterLink, TranslatePipe, RecipeDetailViewComponent],
  template: `
    <div class="space-y-6">
      <header>
        <h1 class="text-2xl font-extrabold tracking-tight sm:text-3xl">{{ 'generators.diet.title' | translate }}</h1>
        <p class="mt-1 text-slate-500 dark:text-slate-400">{{ 'generators.diet.subtitle' | translate }}</p>
      </header>

      @if (info()) {
        <div role="status" class="rounded-xl bg-sky-50 p-3 text-sm text-sky-800 dark:bg-sky-950/40 dark:text-sky-200">
          {{ info() }}
        </div>
      }

      @if (error()) {
        <div role="alert" class="rounded-xl bg-red-50 p-3 text-sm text-red-700 dark:bg-red-950/40 dark:text-red-300">
          {{ error() }}
        </div>
      }

      @if (step() === 'profile') {
        <section class="card space-y-4 p-6">
          <h2 class="text-lg font-bold">{{ 'generators.diet.profileTitle' | translate }}</h2>
          <div class="grid gap-4 sm:grid-cols-2">
            <label class="block text-sm">
              {{ 'generators.diet.heightCm' | translate }}
              <input type="number" class="input mt-1 w-full" [(ngModel)]="profile.heightCm" />
            </label>
            <label class="block text-sm">
              {{ 'generators.diet.weightKg' | translate }}
              <input type="number" class="input mt-1 w-full" [(ngModel)]="profile.weightKg" />
            </label>
            <label class="block text-sm">
              {{ 'generators.diet.age' | translate }}
              <input type="number" class="input mt-1 w-full" [(ngModel)]="profile.age" />
            </label>
            <label class="block text-sm">
              {{ 'generators.diet.sex' | translate }}
              <select class="select mt-1 w-full" [(ngModel)]="profile.sex">
                <option value="male">{{ 'generators.diet.male' | translate }}</option>
                <option value="female">{{ 'generators.diet.female' | translate }}</option>
              </select>
            </label>
            <label class="block text-sm sm:col-span-2">
              {{ 'generators.diet.activity' | translate }}
              <select class="select mt-1 w-full" [(ngModel)]="profile.activityLevel">
                <option value="sedentary">{{ 'generators.diet.sedentary' | translate }}</option>
                <option value="light">{{ 'generators.diet.light' | translate }}</option>
                <option value="moderate">{{ 'generators.diet.moderate' | translate }}</option>
                <option value="active">{{ 'generators.diet.active' | translate }}</option>
                <option value="very_active">{{ 'generators.diet.veryActive' | translate }}</option>
              </select>
            </label>
            <label class="block text-sm sm:col-span-2">
              {{ 'generators.diet.goal' | translate }}
              <select class="select mt-1 w-full" [(ngModel)]="profile.goal">
                <option value="lose_weight">{{ 'generators.diet.loseWeight' | translate }}</option>
                <option value="maintain">{{ 'generators.diet.maintain' | translate }}</option>
                <option value="gain_muscle">{{ 'generators.diet.gainMuscle' | translate }}</option>
                <option value="recomp">{{ 'generators.diet.recomp' | translate }}</option>
              </select>
            </label>
            <label class="block text-sm sm:col-span-2">
              {{ 'generators.diet.allergies' | translate }}
              <textarea class="input mt-1 w-full" rows="2" [(ngModel)]="profile.allergiesNotes"></textarea>
            </label>
          </div>
          <button type="button" class="btn-primary" [disabled]="loading()" (click)="startSession()">
            {{ 'generators.diet.continue' | translate }}
          </button>
        </section>
      }

      @if (step() === 'macros') {
        <section class="card space-y-4 p-6">
          <h2 class="text-lg font-bold">{{ 'generators.diet.macrosTitle' | translate }}</h2>
          @if (macros.rationale) {
            <p class="text-sm text-slate-500 dark:text-slate-400">{{ macros.rationale }}</p>
          }
          <div class="grid gap-4 sm:grid-cols-2">
            <label class="block text-sm">
              {{ 'manage.caloriesKcal' | translate }}
              <input type="number" class="input mt-1 w-full" [(ngModel)]="macros.calories" />
            </label>
            <label class="block text-sm">
              {{ 'manage.proteinG' | translate }}
              <input type="number" class="input mt-1 w-full" [(ngModel)]="macros.proteinG" />
            </label>
            <label class="block text-sm">
              {{ 'manage.fatG' | translate }}
              <input type="number" class="input mt-1 w-full" [(ngModel)]="macros.fatG" />
            </label>
            <label class="block text-sm">
              {{ 'manage.carbsG' | translate }}
              <input type="number" class="input mt-1 w-full" [(ngModel)]="macros.carbsG" />
            </label>
          </div>
          <div class="flex flex-wrap gap-2">
            <button type="button" class="btn-secondary" (click)="step.set('profile')">
              {{ 'common.back' | translate }}
            </button>
            <button type="button" class="btn-primary" [disabled]="loading()" (click)="acceptAndGenerate()">
              {{ 'generators.diet.acceptAndGenerate' | translate }}
            </button>
          </div>
        </section>
      }

      @if (step() === 'plan' && session()) {
        <section class="space-y-4">
          <div class="card p-4">
            <p class="text-sm text-slate-500 dark:text-slate-400">{{ 'generators.diet.planHint' | translate }}</p>
          </div>
          @for (entry of mealsByDate(); track entry.date) {
            <div class="card p-4">
              <div class="mb-3 flex flex-wrap items-center justify-between gap-2">
                <h3 class="font-bold">{{ entry.date }}</h3>
                <span class="text-sm" [class.text-brand-700]="entry.summary?.withinTolerance" [class.text-amber-700]="!entry.summary?.withinTolerance">
                  {{ entry.summary?.totalCalories ?? 0 }} / {{ entry.summary?.targetCalories ?? 0 }} kcal
                  @if (entry.summary?.withinTolerance) { ✓ }
                </span>
              </div>
              <ul class="space-y-2">
                @for (meal of entry.meals; track meal.id) {
                  <li class="flex flex-wrap items-center justify-between gap-2 rounded-lg bg-slate-50 p-3 dark:bg-slate-900/40">
                    <div>
                      <p class="text-xs uppercase text-slate-400">{{ categoryLabel(meal.mealCategory) | translate }}</p>
                      <p class="font-medium">{{ meal.recipeName }}</p>
                      <p class="text-xs text-slate-500">{{ mealMacroLine(meal) }}</p>
                    </div>
                    <div class="flex gap-2">
                      <button type="button" class="btn-secondary !px-2 !py-1 text-xs" (click)="openRecipePreview(meal)">
                        {{ 'generators.diet.viewRecipe' | translate }}
                      </button>
                      <button type="button" class="btn-secondary !px-2 !py-1 text-xs" (click)="toggleLock(meal.id, !meal.isLocked)">
                        {{ (meal.isLocked ? 'generators.diet.unlock' : 'generators.diet.lock') | translate }}
                      </button>
                      <button type="button" class="btn-secondary !px-2 !py-1 text-xs" [disabled]="meal.isLocked" (click)="regenerateMeal(meal.planDate, meal.mealCategory)">
                        ↻
                      </button>
                    </div>
                  </li>
                }
              </ul>
            </div>
          }
          <div class="flex flex-wrap gap-2">
            <button type="button" class="btn-primary" [disabled]="loading()" (click)="commitPlan()">
              {{ 'generators.diet.commit' | translate }}
            </button>
          </div>
        </section>
      }

      @if (step() === 'done') {
        <div class="card space-y-3 p-6 text-brand-800 dark:text-brand-200">
          <p class="font-semibold">{{ 'generators.diet.done' | translate }}</p>
          @if (commitResult()) {
            <p class="text-sm">{{ commitResult() }}</p>
          }
          <div class="flex flex-wrap gap-2">
            <a routerLink="/meal-planner" class="btn-primary">{{ 'nav.mealPlanner' | translate }}</a>
            <button type="button" class="btn-secondary" (click)="reset()">
              {{ 'generators.diet.newPlan' | translate }}
            </button>
          </div>
        </div>
      }

      @if (loading() && step() !== 'done') {
        <p class="text-sm text-slate-400">{{ 'common.loading' | translate }}</p>
      }

      @if (previewMeal()) {
        <div
          class="fixed inset-0 z-50 flex items-end justify-center bg-black/50 p-4 sm:items-center"
          (click)="closeRecipePreview()"
        >
          <div
            class="card max-h-[90vh] w-full max-w-3xl overflow-y-auto p-6"
            role="dialog"
            aria-modal="true"
            (click)="$event.stopPropagation()"
          >
            <div class="mb-4 flex justify-end">
              <button type="button" class="btn-secondary !px-2 !py-2" (click)="closeRecipePreview()">✕</button>
            </div>
            <app-recipe-detail-view [recipe]="mealToRecipeDetail(previewMeal()!)" />
          </div>
        </div>
      }
    </div>
  `,
})
export class DietGeneratorComponent implements OnInit {
  private readonly dietGenerator = inject(DietGeneratorService);
  private readonly translate = inject(TranslateService);
  private readonly router = inject(Router);

  readonly step = signal<Step>('profile');
  readonly sessionId = signal<number | null>(null);
  readonly session = signal<DietGeneratorSession | null>(null);
  readonly loading = signal(false);
  readonly error = signal<string | null>(null);
  readonly info = signal<string | null>(null);
  readonly commitResult = signal<string | null>(null);
  readonly previewMeal = signal<DietGeneratorDraftMeal | null>(null);

  profile: DietUserProfile = { ...DEFAULT_DIET_PROFILE };
  macros = { calories: 2000, proteinG: 150, fatG: 65, carbsG: 200, rationale: '' };

  readonly mealsByDate = computed(() => {
    const s = this.session();
    if (!s) return [];
    const map = new Map<string, typeof s.draftMeals>();
    for (const meal of s.draftMeals) {
      const list = map.get(meal.planDate) ?? [];
      list.push(meal);
      map.set(meal.planDate, list);
    }
    return [...map.entries()]
      .sort(([a], [b]) => a.localeCompare(b))
      .map(([date, meals]) => ({
        date,
        meals,
        summary: s.daySummaries.find((d) => d.planDate === date),
      }));
  });

  ngOnInit(): void {
    this.dietGenerator.fetchProfile().subscribe({
      next: (p) => {
        if (p) this.profile = { ...DEFAULT_DIET_PROFILE, ...p };
      },
    });
  }

  categoryLabel(category: number): string {
    return MEAL_CATEGORY_I18N_KEYS[category as MealCategory] ?? 'categories.unknown';
  }

  mealMacroLine(meal: DietGeneratorDraftMeal): string {
    const parts = [`${meal.calories ?? '?'} kcal`];
    if (meal.proteinG != null) parts.push(`P ${meal.proteinG}g`);
    if (meal.fatG != null) parts.push(`F ${meal.fatG}g`);
    if (meal.carbsG != null) parts.push(`C ${meal.carbsG}g`);
    return parts.join(' · ');
  }

  startSession(): void {
    this.error.set(null);
    this.loading.set(true);
    this.dietGenerator
      .saveProfile(this.profile)
      .pipe(
        switchMap(() =>
          this.dietGenerator.createSession({ planDayCount: 7, calorieToleranceKcal: 10 }),
        ),
        switchMap((session) => {
          this.sessionId.set(session.id);
          this.applyMacros(session);
          return this.dietGenerator.proposeMacros(session.id);
        }),
      )
      .subscribe({
        next: (refined) => {
          this.applyMacros(refined);
          this.step.set('macros');
          this.loading.set(false);
        },
        error: (e) => {
          this.error.set(extractApiError(e, this.translate.instant('generators.diet.error')));
          this.loading.set(false);
        },
      });
  }

  acceptAndGenerate(): void {
    const id = this.sessionId();
    if (!id) return;
    this.error.set(null);
    this.loading.set(true);
    this.dietGenerator
      .acceptMacros(id, this.macros)
      .pipe(switchMap(() => this.dietGenerator.generatePlan(id)))
      .subscribe({
        next: (plan) => {
          this.session.set(plan);
          this.step.set('plan');
          this.loading.set(false);
        },
        error: (e) => {
          this.error.set(extractApiError(e, this.translate.instant('generators.diet.error')));
          this.loading.set(false);
        },
      });
  }

  toggleLock(mealId: number, isLocked: boolean): void {
    const id = this.sessionId();
    if (!id) return;
    this.dietGenerator.toggleMealLock(id, mealId, isLocked).subscribe({
      next: (s) => this.session.set(s),
      error: (e) => this.error.set(extractApiError(e, this.translate.instant('generators.diet.error'))),
    });
  }

  regenerateMeal(planDate: string, mealCategory: number): void {
    const id = this.sessionId();
    if (!id) return;
    this.dietGenerator.regenerateMeal(id, planDate, mealCategory).subscribe({
      next: (s) => {
        this.session.set(s);
        this.error.set(null);
        this.info.set(null);
      },
      error: (e) => {
        if (typeof e === 'object' && e !== null && 'status' in e && (e as { status: number }).status === 400) {
          this.info.set(this.translate.instant('generators.diet.noAlternativeMeals'));
          this.error.set(null);
        } else {
          this.error.set(extractApiError(e, this.translate.instant('generators.diet.error')));
          this.info.set(null);
        }
      },
    });
  }

  openRecipePreview(meal: DietGeneratorDraftMeal): void {
    this.previewMeal.set(meal);
  }

  closeRecipePreview(): void {
    this.previewMeal.set(null);
  }

  mealToRecipeDetail(meal: DietGeneratorDraftMeal): RecipeDetail {
    return {
      id: meal.recipeId,
      name: meal.recipeName,
      mealCategory: meal.mealCategory,
      calories: meal.calories ?? null,
      protein: meal.proteinG ?? null,
      fat: meal.fatG ?? null,
      carbs: meal.carbsG ?? null,
      prepTimeMinutes: meal.prepTimeMinutes ?? null,
      ingredients: (meal.ingredients ?? []).map((ingredient) => ({
        id: ingredient.id,
        name: ingredient.name,
        amountGrams: ingredient.amountGrams ?? null,
        unit: ingredient.unit ?? null,
        sortOrder: ingredient.sortOrder,
        catalogItemId: null,
      })),
      steps: (meal.steps ?? []).map((step) => ({
        id: step.id,
        stepNumber: step.stepNumber,
        description: step.description,
      })),
    };
  }

  commitPlan(): void {
    const id = this.sessionId();
    if (!id) return;
    this.loading.set(true);
    this.dietGenerator.commitPlan(id).subscribe({
      next: (r) => {
        this.commitResult.set(`${r.planStartDate} → ${r.planEndDate}`);
        this.step.set('done');
        this.loading.set(false);
      },
      error: (e) => {
        this.error.set(extractApiError(e, this.translate.instant('generators.diet.error')));
        this.loading.set(false);
      },
    });
  }

  reset(): void {
    this.step.set('profile');
    this.sessionId.set(null);
    this.session.set(null);
    this.commitResult.set(null);
    this.error.set(null);
    void this.router.navigateByUrl('/diet-generator');
  }

  private applyMacros(session: DietGeneratorSession): void {
    if (!session.proposedMacros) return;
    this.macros = {
      calories: session.proposedMacros.calories,
      proteinG: session.proposedMacros.proteinG,
      fatG: session.proposedMacros.fatG,
      carbsG: session.proposedMacros.carbsG,
      rationale: session.proposedMacros.rationale ?? '',
    };
  }
}
