import type { EmailValidationResult } from '../types/EmailAddress';
import { validateEmail } from '../types/EmailAddress';
import { UserId } from '../value-objects/UserId';
import { PasswordHash } from '../value-objects/PasswordHash';
import { StoredUser } from '../repositories/IUserRepository';

export interface UserProps {
  id: UserId;
  displayName: string;
  email?: string;
  passwordHash?: PasswordHash;
  iracingCustomerId?: string;
  primaryDriverId?: string;
  avatarUrl?: string;
}

export class User {
  private readonly id: UserId;
  private displayName: string;
  private email: string | undefined;
  private passwordHash: PasswordHash | undefined;
  private iracingCustomerId: string | undefined;
  private primaryDriverId: string | undefined;
  private avatarUrl: string | undefined;

  private constructor(props: UserProps) {
    if (!props.displayName || !props.displayName.trim()) {
      throw new Error('User displayName cannot be empty');
    }

    this.id = props.id;
    this.displayName = props.displayName.trim();
    this.email = props.email;
    this.iracingCustomerId = props.iracingCustomerId;
    this.primaryDriverId = props.primaryDriverId;
    this.avatarUrl = props.avatarUrl;
  }

  public static create(props: UserProps): User {
    if (props.email) {
      const result: EmailValidationResult = validateEmail(props.email);
      if (!result.success) {
        throw new Error(result.error);
      }
      return new User({
        ...props,
        email: result.email,
      });
    }

    return new User(props);
  }

  public static fromStored(stored: StoredUser): User {
    const passwordHash = stored.passwordHash ? PasswordHash.fromHash(stored.passwordHash) : undefined;
    const userProps: any = {
      id: UserId.fromString(stored.id),
      displayName: stored.displayName,
      email: stored.email,
    };
    if (passwordHash) {
      userProps.passwordHash = passwordHash;
    }
    if (stored.primaryDriverId) {
      userProps.primaryDriverId = stored.primaryDriverId;
    }
    return new User(userProps);
  }

  public getId(): UserId {
    return this.id;
  }

  public getDisplayName(): string {
    return this.displayName;
  }

  public getEmail(): string | undefined {
    return this.email;
  }

  public getPasswordHash(): PasswordHash | undefined {
    return this.passwordHash;
  }

  public getIracingCustomerId(): string | undefined {
    return this.iracingCustomerId;
  }

  public getPrimaryDriverId(): string | undefined {
    return this.primaryDriverId;
  }

  public getAvatarUrl(): string | undefined {
    return this.avatarUrl;
  }
}