/**
 * Jobs Service - Business logic for jobs
 */

import { pocketbaseService } from './pocketbaseService';
import { graphService } from './graphService';
import { cacheService } from './cacheService';
import { tokenService } from './tokenService';
import { CACHE_KEYS } from '@shared/constants';
import type { Job, JobFile, StickyNote, JobListResponse, JobDetailResponse, JobFilesResponse } from '@shared/types/job';

/** Cache TTL for job files (5 minutes) */
const FILES_CACHE_TTL = 300;

class JobsService {
  /**
   * Get list of all jobs
   */
  async getJobs(options?: {
    page?: number;
    perPage?: number;
    filter?: string;
    sort?: string;
  }): Promise<JobListResponse> {
    const result = await pocketbaseService.getJobs(options);

    return {
      jobs: result.items,
      page: options?.page ?? 1,
      perPage: options?.perPage ?? 50,
      totalItems: result.totalItems,
      totalPages: result.totalPages,
    };
  }

  /**
   * Get job detail with files and notes
   */
  async getJobDetail(jobId: string, userId: string): Promise<JobDetailResponse | null> {
    // Get job from PocketBase
    const job = await pocketbaseService.getJob(jobId);
    if (!job) return null;

    // Get notes from PocketBase
    const notes = await pocketbaseService.getJobNotes(jobId);

    // Get files from SharePoint (if job has site/drive configured)
    let files: JobFile[] = [];
    if (job.site_id && job.drive_id) {
      const filesResult = await this.getJobFiles(jobId, userId);
      files = filesResult?.files ?? [];
    }

    return { job, files, notes };
  }

  /**
   * Get files for a job from SharePoint
   */
  async getJobFiles(jobId: string, userId: string): Promise<JobFilesResponse | null> {
    // Try cache first
    const cached = await cacheService.get<JobFilesResponse>(CACHE_KEYS.JOB_FILES(jobId));
    if (cached) {
      return { ...cached, cached: true };
    }

    // Get job to find site/drive info
    const job = await pocketbaseService.getJob(jobId);
    if (!job || !job.site_id || !job.drive_id) {
      return { jobId, files: [], cached: false };
    }

    // Get Graph token for user
    const tokenResult = await tokenService.getToken(userId, 'graph');
    if (!tokenResult) {
      console.error('[JobsService] No Graph token available for user', userId);
      return { jobId, files: [], cached: false };
    }

    try {
      // Fetch files from SharePoint
      const result = await graphService.getFiles(
        tokenResult.token,
        job.site_id,
        job.drive_id,
        job.folder_path
      );

      const response: JobFilesResponse = {
        jobId,
        files: result.files,
        nextLink: result.nextLink,
        cached: false,
      };

      // Cache the result
      await cacheService.set(CACHE_KEYS.JOB_FILES(jobId), response, FILES_CACHE_TTL);

      return response;
    } catch (err) {
      console.error('[JobsService] Failed to get files for job', jobId, err);
      return { jobId, files: [], cached: false };
    }
  }

  /**
   * Search jobs by name or number
   */
  async searchJobs(query: string): Promise<Job[]> {
    const result = await pocketbaseService.getJobs({
      filter: `job_name ~ "${query}" || job_number ~ "${query}"`,
      perPage: 20,
    });
    return result.items;
  }

  /**
   * Get job notes
   */
  async getJobNotes(jobId: string): Promise<StickyNote[]> {
    return pocketbaseService.getJobNotes(jobId);
  }

  /**
   * Create a note for a job
   */
  async createNote(
    jobId: string,
    content: string,
    userId: string,
    options?: { color?: StickyNote['color']; position_x?: number; position_y?: number }
  ): Promise<StickyNote | null> {
    return pocketbaseService.createNote({
      job_id: jobId,
      content,
      color: options?.color ?? 'yellow',
      position_x: options?.position_x ?? 0,
      position_y: options?.position_y ?? 0,
      created_by: userId,
    });
  }

  /**
   * Update a note
   */
  async updateNote(noteId: string, data: Partial<StickyNote>): Promise<StickyNote | null> {
    return pocketbaseService.updateNote(noteId, data);
  }

  /**
   * Delete a note
   */
  async deleteNote(noteId: string): Promise<boolean> {
    return pocketbaseService.deleteNote(noteId);
  }

  /**
   * Invalidate file cache for a job
   */
  async invalidateFileCache(jobId: string): Promise<void> {
    await cacheService.del(CACHE_KEYS.JOB_FILES(jobId));
  }
}

export const jobsService = new JobsService();
