import {
  createProject,
  listProjects,
  getProject,
  updateProject,
  deleteProject
} from '../../services/projectService.js';
import * as projectService from '../../services/projectService.js';

// Mock the pool
jest.mock('../../db/connection.js', () => ({
  pool: {
    query: jest.fn()
  }
}));

import { pool } from '../../db/connection.js';

describe('Project Service', () => {
  afterEach(() => {
    jest.clearAllMocks();
  });
  
  describe('createProject', () => {
    it('should create a project with valid data', async () => {
      const mockProject = {
        id: 1,
        name: 'Test Project',
        description: 'Test description',
        status: 'active',
        color_hex: '#3498db',
        icon_name: 'rocket',
        owner_id: 1,
        created_at: '2026-04-13T00:00:00Z',
        updated_at: '2026-04-13T00:00:00Z'
      };
      
      pool.query.mockResolvedValue({ rows: [mockProject] });
      
      const result = await createProject({
        name: 'Test Project',
        description: 'Test description',
        color_hex: '#3498db',
        icon_name: 'rocket'
      }, 1);
      
      expect(result).toEqual(mockProject);
      expect(pool.query).toHaveBeenCalled();
    });
    
    it('should use default color if not provided', async () => {
      pool.query.mockResolvedValue({ rows: [{ id: 1, color_hex: '#3498db' }] });
      
      await createProject({
        name: 'Test Project'
      }, 1);
      
      const callArgs = pool.query.mock.calls[0];
      expect(callArgs[1][4]).toBe('#3498db'); // color_hex should be default
    });
  });
  
  describe('listProjects', () => {
    it('should list projects with correct filtering', async () => {
      const mockProjects = [
        {
          id: 1,
          name: 'Project 1',
          status: 'active',
          task_count: 5,
          completed_count: 2,
          overdue_count: 0
        }
      ];
      
      pool.query
        .mockResolvedValueOnce({ rows: mockProjects })
        .mockResolvedValueOnce({ rows: [{ total: 1 }] });
      
      const result = await listProjects({
        status: 'active',
        limit: 50,
        offset: 0
      });
      
      expect(result.projects).toEqual(mockProjects);
      expect(result.total).toBe(1);
      expect(pool.query).toHaveBeenCalledTimes(2);
    });
  });
  
  describe('getProject', () => {
    it('should get a project by ID', async () => {
      const mockProject = {
        id: 1,
        name: 'Test Project',
        status: 'active'
      };
      
      pool.query.mockResolvedValue({ rows: [mockProject] });
      
      const result = await getProject(1);
      
      expect(result).toEqual(mockProject);
    });
    
    it('should throw 404 if project not found', async () => {
      pool.query.mockResolvedValue({ rows: [] });
      
      await expect(getProject(999)).rejects.toThrow();
    });
  });
  
  describe('updateProject', () => {
    it('should update project fields', async () => {
      const mockProject = {
        id: 1,
        name: 'Updated Project',
        status: 'archived'
      };
      
      pool.query.mockResolvedValue({ rows: [mockProject] });
      
      const result = await updateProject(1, {
        name: 'Updated Project',
        status: 'archived'
      });
      
      expect(result.name).toBe('Updated Project');
      expect(result.status).toBe('archived');
    });
    
    it('should not update fields not provided', async () => {
      pool.query.mockResolvedValue({ rows: [{ id: 1, name: 'Test' }] });
      
      await updateProject(1, {
        name: 'Test'
      });
      
      const query = pool.query.mock.calls[0][0];
      expect(query).toContain('name');
      expect(query).toContain('updated_at');
    });
  });
  
  describe('deleteProject', () => {
    it('should delete a project', async () => {
      pool.query.mockResolvedValue({ rows: [{ id: 1 }] });
      
      const result = await deleteProject(1);
      
      expect(result.id).toBe(1);
    });
    
    it('should throw 404 if project not found', async () => {
      pool.query.mockResolvedValue({ rows: [] });
      
      await expect(deleteProject(999)).rejects.toThrow();
    });
  });
});
