import { UserRepository } from '../models/repositories/UserRepository';
import { AppError } from '../utils/AppError';
import { TimezoneService } from './TimezoneService';
import { ProfileEnhancementService } from './ProfileEnhancementService';
import { LinkedInProfileFetcher } from './LinkedInProfileFetcher';
import { User } from '../models/entities/User.entity';

export class UserService {
  constructor(
    private userRepo = new UserRepository(),
    private timezoneService = new TimezoneService(),
    private profileEnhancement = new ProfileEnhancementService(),
    private linkedInFetcher = new LinkedInProfileFetcher(),
  ) {}

  async getById(userId: string): Promise<User> {
    const user = await this.userRepo.findById(userId);
    if (!user) throw new AppError('not_found', 404, 'User not found.');
    return user;
  }

  async updateProfile(
    userId: string,
    data: {
      fullName?: string;
      timezone?: string;
      avatarUrl?: string | null;
      bannerUrl?: string | null;
      logoUrl?: string | null;
      tagline?: string | null;
      headline?: string | null;
      bio?: string | null;
      jobTitle?: string | null;
      company?: string | null;
      location?: string | null;
      linkedinUrl?: string | null;
    },
  ): Promise<User> {
    if (data.timezone) {
      await this.timezoneService.assertActiveTimezone(data.timezone);
    }
    return this.userRepo.update(userId, data);
  }

  async enhanceProfileFields(
    userId: string,
    fields: {
      fullName?: string;
      headline?: string;
      bio?: string;
      jobTitle?: string;
      company?: string;
      location?: string;
    },
  ) {
    await this.getById(userId);
    return this.profileEnhancement.enhance(fields);
  }

  async fetchLinkedInProfile(linkedinUrl: string) {
    const fetched = await this.linkedInFetcher.fetchProfile(linkedinUrl);
    const enhanced = this.profileEnhancement.enhanceLinkedInImport({
      fullName: fetched.fullName,
      headline: fetched.headline,
      bio: fetched.bio,
      jobTitle: fetched.jobTitle,
      company: fetched.company,
      location: fetched.location,
    });

    return {
      linkedinUrl: this.linkedInFetcher.normalizeUrl(linkedinUrl),
      fetched,
      enhanced: {
        ...enhanced,
        education: fetched.education ?? null,
        experiences: fetched.experiences ?? [],
        avatarUrl: fetched.avatarUrl ?? null,
      },
      warnings: fetched.fetchWarnings ?? [],
    };
  }

  async importFromLinkedIn(
    userId: string,
    input: {
      linkedinUrl: string;
      bio?: string;
      avatarUrl?: string | null;
    },
  ): Promise<User> {
    const user = await this.getById(userId);
    const linkedinUrl = this.linkedInFetcher.normalizeUrl(input.linkedinUrl);

    let fetched: Awaited<ReturnType<LinkedInProfileFetcher['fetchProfile']>> | null = null;
    let enhanced: ReturnType<ProfileEnhancementService['enhanceLinkedInImport']> = {};

    try {
      const result = await this.fetchLinkedInProfile(input.linkedinUrl);
      fetched = result.fetched;
      enhanced = result.enhanced;
    } catch {
      if (!input.bio?.trim()) {
        throw new AppError(
          'linkedin_fetch_failed',
          502,
          'Could not fetch LinkedIn profile. Paste your About section below and import again.',
        );
      }
    }

    const fullName = enhanced.fullName ?? fetched?.fullName;
    const avatarUrl = input.avatarUrl ?? fetched?.avatarUrl ?? undefined;
    const bio = input.bio?.trim()
      ? this.profileEnhancement.polishLinkedInAbout(input.bio)
      : enhanced.bio ?? fetched?.bio ?? null;

    return this.userRepo.update(userId, {
      linkedinUrl,
      fullName: fullName && fullName !== user.fullName ? fullName : undefined,
      headline: enhanced.headline ?? fetched?.headline ?? null,
      bio,
      jobTitle: enhanced.jobTitle ?? fetched?.jobTitle ?? null,
      company: enhanced.company ?? fetched?.company ?? null,
      location: enhanced.location ?? fetched?.location ?? null,
      avatarUrl,
    });
  }
}
