import { Component, inject, OnInit, signal } from '@angular/core';
import {
  AbstractControl,
  FormBuilder,
  ReactiveFormsModule,
  ValidationErrors,
  Validators,
} from '@angular/forms';
import { Router, RouterLink } from '@angular/router';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import { AuthService } from '../../core/services/auth.service';
import { ThemeService } from '../../core/services/theme.service';
import { LanguageSwitcherComponent } from '../../shared/components/language-switcher.component';
import { extractApiError } from '../../core/utils/api-error.util';

function passwordStrength(control: AbstractControl): ValidationErrors | null {
  const value = control.value as string;
  if (!value) return null;
  const errors: ValidationErrors = {};
  if (value.length < 8) errors['minLength'] = true;
  if (!/[A-Z]/.test(value)) errors['uppercase'] = true;
  if (!/[a-z]/.test(value)) errors['lowercase'] = true;
  if (!/[0-9]/.test(value)) errors['digit'] = true;
  return Object.keys(errors).length ? errors : null;
}

function passwordsMatch(group: AbstractControl): ValidationErrors | null {
  const password = group.get('password')?.value;
  const confirm = group.get('confirmPassword')?.value;
  return password === confirm ? null : { mismatch: true };
}

@Component({
  selector: 'app-register',
  standalone: true,
  imports: [ReactiveFormsModule, RouterLink, TranslatePipe, LanguageSwitcherComponent],
  template: `
    <div
      class="relative flex min-h-screen items-center justify-center bg-gradient-to-br from-brand-50 to-slate-100 px-4 dark:from-slate-950 dark:to-slate-900"
    >
      <div class="absolute right-4 top-4 flex items-center gap-2">
        <app-language-switcher />
        <button
          type="button"
          (click)="theme.toggle()"
          class="btn-secondary !px-2.5 !py-2"
          [attr.aria-label]="'nav.toggleTheme' | translate"
        >
          @if (theme.theme() === 'dark') {
            <svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
              <circle cx="12" cy="12" r="4" />
              <path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2" />
            </svg>
          } @else {
            <svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
              <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
            </svg>
          }
        </button>
      </div>

      <div class="w-full max-w-md">
        <div class="mb-8 flex flex-col items-center text-center">
          <span class="grid h-14 w-14 place-items-center rounded-2xl bg-brand-600 text-white shadow-lg">
            <svg class="h-7 w-7" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
              <path d="M3 2v7c0 1.1.9 2 2 2h4a2 2 0 0 0 2-2V2" />
              <path d="M7 2v20" />
              <path d="M21 15V2a5 5 0 0 0-5 5v6c0 1.1.9 2 2 2h3Zm0 0v7" />
            </svg>
          </span>
          <h1 class="mt-4 text-2xl font-extrabold tracking-tight">{{ 'auth.createAccountTitle' | translate }}</h1>
          <p class="mt-1 text-sm text-slate-500 dark:text-slate-400">{{ 'auth.createAccountSubtitle' | translate }}</p>
        </div>

        <form [formGroup]="form" (ngSubmit)="onSubmit()" class="card space-y-5 p-6 sm:p-8" novalidate>
          @if (error()) {
            <div role="alert" class="flex items-start gap-2 rounded-xl bg-red-50 p-3 text-sm text-red-700 dark:bg-red-950/40 dark:text-red-300">
              <span aria-hidden="true">⚠</span>
              <span>{{ error() }}</span>
            </div>
          }

          <div>
            <label for="email" class="mb-1.5 block text-sm font-medium">{{ 'auth.email' | translate }}</label>
            <input id="email" type="email" formControlName="email" autocomplete="email" class="input" [placeholder]="'auth.emailPlaceholder' | translate" />
            @if (form.controls.email.touched && form.controls.email.errors?.['required']) {
              <p class="mt-1.5 text-sm text-red-600">{{ 'validation.emailRequired' | translate }}</p>
            }
            @if (form.controls.email.touched && form.controls.email.errors?.['email']) {
              <p class="mt-1.5 text-sm text-red-600">{{ 'validation.emailInvalid' | translate }}</p>
            }
          </div>

          <div>
            <label for="userName" class="mb-1.5 block text-sm font-medium">
              {{ 'auth.displayName' | translate }}
              <span class="text-slate-400">({{ 'common.optional' | translate }})</span>
            </label>
            <input id="userName" type="text" formControlName="userName" autocomplete="name" class="input" [placeholder]="'auth.displayNamePlaceholder' | translate" />
            @if (form.controls.userName.touched && form.controls.userName.errors?.['maxlength']) {
              <p class="mt-1.5 text-sm text-red-600">{{ 'validation.displayNameTooLong' | translate }}</p>
            }
          </div>

          <div>
            <label for="password" class="mb-1.5 block text-sm font-medium">{{ 'auth.password' | translate }}</label>
            <input id="password" type="password" formControlName="password" autocomplete="new-password" class="input" placeholder="••••••••" />
            @if (form.controls.password.touched && form.controls.password.errors?.['minLength']) {
              <p class="mt-1.5 text-sm text-red-600">{{ 'validation.passwordMinLength' | translate }}</p>
            }
            @if (form.controls.password.touched && form.controls.password.errors?.['uppercase']) {
              <p class="mt-1.5 text-sm text-red-600">{{ 'validation.passwordUppercase' | translate }}</p>
            }
            @if (form.controls.password.touched && form.controls.password.errors?.['lowercase']) {
              <p class="mt-1.5 text-sm text-red-600">{{ 'validation.passwordLowercase' | translate }}</p>
            }
            @if (form.controls.password.touched && form.controls.password.errors?.['digit']) {
              <p class="mt-1.5 text-sm text-red-600">{{ 'validation.passwordDigit' | translate }}</p>
            }
            <p class="mt-1 text-xs text-slate-500 dark:text-slate-400">{{ 'auth.passwordHint' | translate }}</p>
          </div>

          <div>
            <label for="confirmPassword" class="mb-1.5 block text-sm font-medium">{{ 'auth.confirmPassword' | translate }}</label>
            <input id="confirmPassword" type="password" formControlName="confirmPassword" autocomplete="new-password" class="input" placeholder="••••••••" />
            @if (form.controls.confirmPassword.touched && form.controls.confirmPassword.errors?.['required']) {
              <p class="mt-1.5 text-sm text-red-600">{{ 'validation.confirmPasswordRequired' | translate }}</p>
            }
            @if (form.touched && form.errors?.['mismatch']) {
              <p class="mt-1.5 text-sm text-red-600">{{ 'validation.passwordsMismatch' | translate }}</p>
            }
          </div>

          <button type="submit" [disabled]="pending()" class="btn-primary w-full">
            @if (pending()) {
              <span class="inline-block h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent"></span>
            }
            {{ pending() ? ('auth.creatingAccount' | translate) : ('auth.createAccount' | translate) }}
          </button>

          <p class="text-center text-sm text-slate-500 dark:text-slate-400">
            {{ 'auth.hasAccount' | translate }}
            <a routerLink="/login" class="font-semibold text-brand-600 hover:text-brand-700">
              {{ 'auth.signIn' | translate }}
            </a>
          </p>
        </form>
      </div>
    </div>
  `,
})
export class RegisterComponent implements OnInit {
  private readonly fb = inject(FormBuilder);
  private readonly auth = inject(AuthService);
  private readonly router = inject(Router);
  private readonly translate = inject(TranslateService);
  readonly theme = inject(ThemeService);

  readonly pending = signal(false);
  readonly error = signal<string | null>(null);

  readonly form = this.fb.nonNullable.group(
    {
      email: ['', [Validators.required, Validators.email]],
      userName: ['', Validators.maxLength(256)],
      password: ['', passwordStrength],
      confirmPassword: ['', Validators.required],
    },
    { validators: passwordsMatch },
  );

  ngOnInit(): void {
    if (this.auth.isAuthenticated()) {
      void this.router.navigateByUrl('/');
    }
  }

  async onSubmit(): Promise<void> {
    this.form.markAllAsTouched();
    if (this.form.invalid) return;

    this.pending.set(true);
    this.error.set(null);
    const { email, password, userName } = this.form.getRawValue();
    try {
      await this.auth.register({
        email,
        password,
        userName: userName.trim() || undefined,
      });
      void this.router.navigateByUrl('/');
    } catch (err) {
      this.error.set(extractApiError(err, this.translate.instant('errors.registerFailed')));
    } finally {
      this.pending.set(false);
    }
  }
}
