/**
 * @aurora-catalyst-generated
 * @source cliter/o-auth/client.aurora.yaml
 */
import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  effect,
  inject,
  input,
  output,
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import {
  MultipleSearchSelect,
  ToOptionsPipe,
  ValidationMessagePipe,
  type Option,
} from '@aurora';
import { provideTranslocoScope, TranslocoDirective } from '@jsverse/transloco';
import { HlmFieldImports } from '@spartan-ng/helm/field';
import { HlmInputImports } from '@spartan-ng/helm/input';
import { HlmLabelImports } from '@spartan-ng/helm/label';
import { HlmSelectImports } from '@spartan-ng/helm/select';
import { HlmSwitchImports } from '@spartan-ng/helm/switch';
import { type OAuthApplication, type OAuthClient } from '@src/src/app/aurora.types';

@Component({
  selector: 'au-client-form',
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [
    ReactiveFormsModule,
    TranslocoDirective,
    ValidationMessagePipe,
    HlmFieldImports,
    HlmInputImports,
    HlmLabelImports,
    HlmSwitchImports,
    HlmSelectImports,
    MultipleSearchSelect,
    ToOptionsPipe,
  ],
  providers: [provideTranslocoScope('o-auth')],
  template: `
    <ng-container *transloco="let t; scope: 'o-auth'">
      <!-- #region AURORA:FORM-FIELDS-START -->
      <form
        class="grid grid-cols-1 gap-x-4 gap-y-5 md:grid-cols-12"
        [formGroup]="signalForm"
        (ngSubmit)="submit()"
      >
        <hlm-field class="col-span-12 md:col-span-12">
          <label
            hlmLabel
            for="grantType"
          >
            {{ t('o-auth.client.GrantType') }}
            <span
              aria-hidden="true"
              class="text-muted-foreground/70 align-top text-xs"
            >
              *
            </span>
          </label>
          <hlm-select formControlName="grantType">
            <hlm-select-trigger
              aria-required="true"
              buttonId="grantType"
            >
              <hlm-select-placeholder>{{ t('Select') }}</hlm-select-placeholder>
              <ng-template
                hlmSelectValueTemplate
                let-value
              >
                {{ t('o-auth.client.GrantType.' + value) }}
              </ng-template>
            </hlm-select-trigger>
            <hlm-select-content *hlmSelectPortal>
              <hlm-select-item value="AUTHORIZATION_CODE">
                {{ t('o-auth.client.GrantType.AUTHORIZATION_CODE') }}
              </hlm-select-item>
              <hlm-select-item value="CLIENT_CREDENTIALS">
                {{ t('o-auth.client.GrantType.CLIENT_CREDENTIALS') }}
              </hlm-select-item>
              <hlm-select-item value="PASSWORD">
                {{ t('o-auth.client.GrantType.PASSWORD') }}
              </hlm-select-item>
              <hlm-select-item value="REFRESH_TOKEN">
                {{ t('o-auth.client.GrantType.REFRESH_TOKEN') }}
              </hlm-select-item>
            </hlm-select-content>
          </hlm-select>
          <hlm-field-error>
            {{ signalForm.get('grantType')?.errors | validationMessage }}
          </hlm-field-error>
        </hlm-field>

        <hlm-field class="col-span-12 md:col-span-12">
          <label
            hlmLabel
            for="applicationIds"
          >
            {{ t('o-auth.client.ApplicationIds') }}
          </label>
          <au-multiple-search-select
            [inputId]="'applicationIds'"
            [value]="signalForm.controls['applicationIds'].value ?? []"
            [options]="applicationOptions() | toOptions: '{name}'"
            [placeholder]="t('Select')"
            [emptyMessage]="t('NoResults')"
            (valueChange)="
              signalForm.controls['applicationIds'].setValue($event); signalForm.markAsDirty()
            "
            (touched)="signalForm.controls['applicationIds'].markAsTouched()"
          />
          <hlm-field-error>
            {{ signalForm.get('applicationIds')?.errors | validationMessage }}
          </hlm-field-error>
        </hlm-field>

        <hlm-field class="col-span-12 md:col-span-12">
          <label
            hlmLabel
            for="scopeOptions"
          >
            {{ t('o-auth.client.ScopeOptions') }}
          </label>
          <au-multiple-search-select
            [inputId]="'scopeOptions'"
            [value]="signalForm.controls['scopeOptions'].value ?? []"
            [options]="scopeOptions()"
            [placeholder]="t('Select')"
            [emptyMessage]="t('o-auth.client.NoScopes')"
            (valueChange)="
              signalForm.controls['scopeOptions'].setValue($event); signalForm.markAsDirty()
            "
            (touched)="signalForm.controls['scopeOptions'].markAsTouched()"
          />
          <hlm-field-error>
            {{ signalForm.get('scopeOptions')?.errors | validationMessage }}
          </hlm-field-error>
        </hlm-field>

        <hlm-field class="col-span-12 md:col-span-8">
          <label
            hlmLabel
            for="name"
          >
            {{ t('o-auth.client.Name') }}
            <span
              aria-hidden="true"
              class="text-muted-foreground/70 align-top text-xs"
            >
              *
            </span>
          </label>
          <input
            id="name"
            aria-required="true"
            hlmInput
            formControlName="name"
            maxlength="128"
          />
          <hlm-field-error>
            {{ signalForm.get('name')?.errors | validationMessage }}
          </hlm-field-error>
        </hlm-field>
        <hlm-field class="col-span-12 pt-9 md:col-span-4">
          <label
            class="flex items-center"
            hlmLabel
            for="isMaster"
          >
            <hlm-switch
              class="mr-2"
              inputId="isMaster"
              formControlName="isMaster"
            />
            {{ t('o-auth.client.IsMaster') }}
          </label>
        </hlm-field>
        <hlm-field class="col-span-12 md:col-span-12">
          <label
            hlmLabel
            for="secret"
          >
            {{ t('o-auth.client.Secret') }}
            <span
              aria-hidden="true"
              class="text-muted-foreground/70 align-top text-xs"
            >
              *
            </span>
          </label>
          <input
            id="secret"
            aria-required="true"
            hlmInput
            formControlName="secret"
            maxlength="128"
          />
          <hlm-field-error>
            {{ signalForm.get('secret')?.errors | validationMessage }}
          </hlm-field-error>
        </hlm-field>
        <hlm-field class="col-span-12 md:col-span-12">
          <label
            hlmLabel
            for="authUrl"
          >
            {{ t('o-auth.client.AuthUrl') }}
          </label>
          <input
            id="authUrl"
            hlmInput
            formControlName="authUrl"
            maxlength="2046"
          />
          <hlm-field-error>
            {{ signalForm.get('authUrl')?.errors | validationMessage }}
          </hlm-field-error>
        </hlm-field>
        <hlm-field class="col-span-12 md:col-span-12">
          <label
            hlmLabel
            for="redirect"
          >
            {{ t('o-auth.client.Redirect') }}
          </label>
          <input
            id="redirect"
            hlmInput
            formControlName="redirect"
            maxlength="2046"
          />
          <hlm-field-error>
            {{ signalForm.get('redirect')?.errors | validationMessage }}
          </hlm-field-error>
        </hlm-field>

        <hlm-field class="col-span-12 md:col-span-4">
          <label
            hlmLabel
            for="accessTokenLifetimeSeconds"
          >
            {{ t('o-auth.client.AccessTokenLifetimeSeconds') }}
          </label>
          <input
            id="accessTokenLifetimeSeconds"
            type="number"
            step="1"
            hlmInput
            formControlName="accessTokenLifetimeSeconds"
          />
          <hlm-field-error>
            {{ signalForm.get('accessTokenLifetimeSeconds')?.errors | validationMessage }}
          </hlm-field-error>
        </hlm-field>
        <hlm-field class="col-span-12 md:col-span-4">
          <label
            hlmLabel
            for="refreshTokenLifetimeSeconds"
          >
            {{ t('o-auth.client.RefreshTokenLifetimeSeconds') }}
          </label>
          <input
            id="refreshTokenLifetimeSeconds"
            type="number"
            step="1"
            hlmInput
            formControlName="refreshTokenLifetimeSeconds"
          />
          <hlm-field-error>
            {{ signalForm.get('refreshTokenLifetimeSeconds')?.errors | validationMessage }}
          </hlm-field-error>
        </hlm-field>
        <hlm-field class="col-span-12 pt-9 md:col-span-3">
          <label
            class="flex items-center"
            hlmLabel
            for="isActive"
          >
            <hlm-switch
              class="mr-2"
              inputId="isActive"
              formControlName="isActive"
            />
            {{ t('o-auth.client.IsActive') }}
          </label>
        </hlm-field>
      </form>
      <!-- #endregion AURORA:FORM-FIELDS-END -->
    </ng-container>
  `,
})
export class ClientFormComponent {
  // injections
  private readonly fb = inject(FormBuilder);
  private readonly cdr = inject(ChangeDetectorRef);

  // inputs
  readonly initial = input<OAuthClient | null>(null);
  readonly mode = input.required<'new' | 'edit'>();

  // outputs
  readonly save = output<OAuthClient>();
  readonly cancel = output<void>();
  readonly applicationOptions = input<OAuthApplication[]>([]);
  readonly scopeOptions = input<Option[]>([]);

  readonly signalForm: FormGroup = this.fb.group({
    id: [null],
    grantType: [null, [Validators.required]],
    applicationIds: [[]],
    name: ['', [Validators.required, Validators.maxLength(128)]],
    secret: ['', [Validators.required, Validators.maxLength(128)]],
    authUrl: ['', [Validators.maxLength(2046)]],
    redirect: ['', [Validators.maxLength(2046)]],
    scopeOptions: [[]],
    accessTokenLifetimeSeconds: [null],
    refreshTokenLifetimeSeconds: [null],
    isActive: [false],
    isMaster: [false],
  });
  constructor() {
    effect(() => {
      const init = this.initial();
      if (!init) return;
      this.signalForm.reset({
        ...init,
        applicationIds: (init.applications ?? []).flatMap((application) =>
          application?.id ? [application.id] : [],
        ),
        scopeOptions: init.scopeOptions ?? [],
      });
    });

    // Bridge FormControl.valueChanges to OnPush change detection. Aurora wrapper
    // widgets (search-select family, grid-select-element) use [value]/(valueChange)
    // bindings instead of formControlName, so they don't subscribe to value
    // changes through Angular's reactive-forms directive. Without this, the
    // form's effect-driven reset() in edit mode silently leaves the widget view
    // stale.
    this.signalForm.valueChanges
      .pipe(takeUntilDestroyed())
      .subscribe(() => this.cdr.markForCheck());
  }

  submit(): void {
    if (this.signalForm.invalid) {
      this.signalForm.markAllAsTouched();
      return;
    }
    this.save.emit(this.signalForm.value as OAuthClient);
  }
}
