import { CommonModule } from '@angular/common';
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';

import { CatalogCrudConfig, CatalogFieldConfig, CatalogLookupData, CatalogOption } from '../../../models/catalog-crud.model';
import { FormFieldComponent } from '../../../shared/components/form-field/form-field.component';
import { CatalogCrudService } from '../../../services/catalog-crud.service';

interface CatalogFormDialogData {
  config: CatalogCrudConfig;
  entity: Record<string, unknown> | null;
  lookupData: CatalogLookupData;
}

@Component({
  selector: 'app-catalog-form-dialog',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule, FormFieldComponent],
  templateUrl: './catalog-form-dialog.page.html',
  styleUrls: ['./catalog-form-dialog.page.scss']
})
export class CatalogFormDialogPage implements OnInit {
  form: FormGroup;
  isEditMode = false;
  saving = false;
  errorMessage = '';

  constructor(
    private fb: FormBuilder,
    private catalogCrudService: CatalogCrudService,
    public dialogRef: MatDialogRef<CatalogFormDialogPage>,
    @Inject(MAT_DIALOG_DATA) public data: CatalogFormDialogData
  ) {
    this.form = this.buildForm();
  }

  ngOnInit(): void {
    if (!this.data.entity) {
      return;
    }

    this.isEditMode = true;
    const mappedValue = this.data.config.toFormValue
      ? this.data.config.toFormValue(this.data.entity)
      : this.data.entity;
    this.form.patchValue(mappedValue);
  }

  getSafeControl(name: string): FormControl {
    return (this.form.get(name) as FormControl) ?? new FormControl();
  }

  getOptions(field: CatalogFieldConfig): CatalogOption[] {
    if (field.options?.length) {
      return field.options;
    }

    if (!field.lookupKey) {
      return [];
    }

    const entries = this.data.lookupData[field.lookupKey] ?? [];
    return entries.map(entry => ({
      label: String(entry['name'] ?? entry['description'] ?? entry['id']),
      value: (entry['id'] as number | string | boolean | null) ?? null
    }));
  }

  submit(): void {
    if (this.form.invalid) {
      this.form.markAllAsTouched();
      return;
    }

    this.saving = true;
    this.errorMessage = '';

    const payload = this.data.config.toPayload(this.form.getRawValue());
    const request$ = this.isEditMode && this.data.entity?.['id']
      ? this.catalogCrudService.update(
          this.data.config.endpoint,
          Number(this.data.entity['id']),
          payload,
          this.data.config.updateMethod
        )
      : this.catalogCrudService.create(this.data.config.endpoint, payload);

    request$.subscribe({
      next: () => {
        this.saving = false;
        this.dialogRef.close({
          saved: true,
          message: this.isEditMode
            ? `${this.data.config.singular} actualizada correctamente.`
            : `${this.data.config.singular} creada correctamente.`
        });
      },
      error: () => {
        this.saving = false;
        this.errorMessage = this.isEditMode
          ? `No se pudo actualizar la ${this.data.config.singular}.`
          : `No se pudo crear la ${this.data.config.singular}.`;
      }
    });
  }

  private buildForm(): FormGroup {
    const controls: Record<string, FormControl> = {};

    this.data.config.fields.forEach(field => {
      const validators = [];

      if (field.required) {
        validators.push(Validators.required);
      }

      if (field.type === 'number' && field.min !== undefined) {
        validators.push(Validators.min(field.min));
      }

      controls[field.key] = this.fb.control(null, validators);
    });

    return this.fb.group(controls);
  }
}
