import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { PageSeoMetadata } from './entities/page_seo_metadata.entity';
import { CityService } from '../city/city.service';
import { IndustriesService } from '../industries/industries.service';
import { EducationLevelsService } from '../education_levels/education_levels.service';
import { RolesService } from '../roles/roles.service';
import { PageSeoAuditService } from './page_seo_audit.service';
import { JobTypeService } from '../job_type/job_type.service';
import { JobCategoriesService } from '../job_categories/job_categories.service';

@Injectable()
export class PageSeoMetadataService {
  constructor(
    @InjectRepository(PageSeoMetadata)
    private readonly seoRepository: Repository<PageSeoMetadata>,
    private readonly cityService: CityService,
    private readonly industriesService: IndustriesService,
    private readonly educationService: EducationLevelsService,
    private readonly rolesService: RolesService,
    private readonly jobTypeService: JobTypeService,
    private readonly jobCategoriesService: JobCategoriesService,
    private readonly auditService: PageSeoAuditService,
  ) {}

  /**
   * Fetches published and active custom SEO metadata for a specific route and slug combination.
   * This is heavily optimized since it uses the compound index: (route_type, slug, locale).
   */
  async getSeoBySlug(
    route_type: string,
    slug: string,
    locale: string = 'en',
  ): Promise<PageSeoMetadata> {
    // Sanitize slug: trim and remove trailing/leading slashes
    const cleanSlug = slug?.trim().replace(/^\/|\/$/g, '') || '';

    // console.log(`🔍 [Backseo] SEO Query: route=${route_type}, slug=${cleanSlug}, locale=${locale}`);

    const seoData = await this.seoRepository.findOne({
      where: {
        route_type: route_type as any,
        slug: cleanSlug,
        locale: locale || 'en',
        status: 'published',
        is_active: true,
      },
      select: [
        'id',
        'meta_title',
        'meta_description',
        'meta_keywords',
        'robots',
        'content_title',
        'content_description',
        'faq_title',
        'faqs',
        'status',
        'is_active',
        'route_type',
        'slug',
        'locale',
      ],
    });

    if (!seoData) {
      // console.log(`⚠️ [Backseo] No SEO Record found for: ${route_type}/${cleanSlug}`);
      return null;
    }

    // console.log(`✅ [Backseo] Found SEO: ${seoData.meta_title}`);
    return seoData;
  }

  /**
   * Create or Update SEO metadata.
   */
  async upsertPageSeo(
    dto: Partial<PageSeoMetadata>,
    userId?: number,
  ): Promise<PageSeoMetadata> {
    const { route_type, slug, locale = 'en' } = dto;
    if (!route_type || slug === undefined || slug === null)
      throw new Error('Missing mandatory fields');

    let existing = await this.seoRepository.findOne({
      where: { route_type: route_type as any, slug, locale },
    });

    if (existing) return this.updateSeo(existing.id, dto, userId);
    return this.createSeo(dto, userId);
  }

  async createSeo(
    dto: Partial<PageSeoMetadata>,
    userId?: number,
  ): Promise<PageSeoMetadata> {
    const neu = this.seoRepository.create({
      ...dto,
      created_by: userId || 1,
      updated_by: userId || 1,
    });
    const saved = await this.seoRepository.save(neu);
    await this.auditService.logChange({
      seo_id: saved.id,
      action_type: 'CREATE',
      oldData: null,
      newData: saved,
      user_id: userId || 1,
    });
    return saved;
  }

  async updateSeo(
    id: number,
    dto: Partial<PageSeoMetadata>,
    userId?: number,
  ): Promise<PageSeoMetadata> {
    const existing = await this.seoRepository.findOneBy({ id });
    if (!existing) throw new NotFoundException('SEO metadata not found');

    // Capture state for audit
    const oldData = { ...existing };

    Object.assign(existing, {
      ...dto,
      updated_by: userId || 1,
      updated_at: new Date(),
    });
    const saved = await this.seoRepository.save(existing);

    await this.auditService.logChange({
      seo_id: saved.id,
      action_type: 'UPDATE',
      oldData,
      newData: saved,
      user_id: userId || 1,
    });

    return saved;
  }

  async toggleActiveStatus(
    id: number,
    userId?: number,
  ): Promise<PageSeoMetadata> {
    const existing = await this.seoRepository.findOneBy({ id });
    if (!existing) throw new NotFoundException('SEO metadata not found');

    const oldData = { ...existing };
    existing.is_active = !existing.is_active;
    const saved = await this.seoRepository.save(existing);

    await this.auditService.logChange({
      seo_id: saved.id,
      action_type: 'TOGGLE_ACTIVE',
      oldData,
      newData: saved,
      user_id: userId || 1,
    });

    return saved;
  }

  // Aggregate Search Methods
  async findAll(): Promise<PageSeoMetadata[]> {
    return this.seoRepository.find({
      order: { updated_at: 'DESC' },
    });
  }

  async searchCities(query: string) {
    return this.cityService.search(query);
  }
  async searchIndustries(query: string) {
    return this.industriesService.search(query);
  }
  async searchEducation(query: string) {
    return this.educationService.search(query);
  }
  async searchRoles(query: string) {
    return this.rolesService.search(query);
  }
  async searchJobTypes(query: string) {
    return this.jobTypeService.search(query);
  }
  async searchCategories(query: string) {
    return this.jobCategoriesService.search(query);
  }
}
