import * as fs from 'node:fs/promises';
import * as os from 'node:os';
import * as path from 'node:path';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { ImmichClient, ImmichIntegration, immichProfile, type IImmichSnapshot } from '../../ts/integrations/immich/index.js';

tap.test('polls live Immich server data through the local HTTP API', async () => {
  const originalFetch = globalThis.fetch;
  const requests: Array<{ url: string; method: string; apiKey?: string }> = [];
  globalThis.fetch = (async (inputArg: RequestInfo | URL, initArg?: RequestInit) => {
    const url = new URL(String(inputArg));
    const headers = initArg?.headers as Record<string, string>;
    requests.push({ url: url.toString(), method: initArg?.method || 'GET', apiKey: headers?.['x-api-key'] });

    if (url.pathname === '/api/users/me') {
      return jsonResponse({ id: 'user-1', name: 'Ada', email: 'ada@example.test', isAdmin: true });
    }
    if (url.pathname === '/api/server/about') {
      return jsonResponse({ version: 'v1.134.1', licensed: true, versionUrl: 'https://example.test/version' });
    }
    if (url.pathname === '/api/server/storage') {
      return jsonResponse({ diskAvailableRaw: 600, diskAvailable: '600 B', diskSizeRaw: 1000, diskSize: '1000 B', diskUsagePercentage: 40, diskUseRaw: 400, diskUse: '400 B' });
    }
    if (url.pathname === '/api/server/statistics') {
      return jsonResponse({ photos: 12, videos: 3, usage: 400, usagePhotos: 250, usageVideos: 150, usageByUser: [] });
    }
    if (url.pathname === '/api/server/version-check') {
      return jsonResponse({ checkedAt: '2026-05-11T00:00:00.000Z', releaseVersion: 'v1.135.0' });
    }
    return jsonResponse({ message: 'not found' }, 404);
  }) as typeof globalThis.fetch;

  try {
    const client = new ImmichClient({ url: 'http://immich.local:2283', apiKey: 'secret' });
    const snapshot = await client.getSnapshot();
    const runtime = await new ImmichIntegration().setup({ url: 'http://immich.local:2283', apiKey: 'secret' }, {});
    const status = await runtime.callService!({ domain: 'immich', service: 'status', target: {} });

    expect(snapshot.online).toBeTrue();
    expect(snapshot.source).toEqual('http');
    expect(snapshot.device.name).toEqual('Ada');
    expect(snapshot.entities.find((entityArg) => entityArg.id === 'disk_size')?.state).toEqual(1000);
    expect(snapshot.entities.find((entityArg) => entityArg.id === 'photos_count')?.state).toEqual(12);
    expect(snapshot.entities.find((entityArg) => entityArg.id === 'update')?.attributes?.latestVersion).toEqual('v1.135.0');
    expect((status.data as IImmichSnapshot).online).toBeTrue();
    expect(requests.every((requestArg) => requestArg.apiKey === 'secret')).toBeTrue();
    await runtime.destroy();
  } finally {
    globalThis.fetch = originalFetch;
  }
});

tap.test('uploads a local file to Immich and adds it to an album', async () => {
  const originalFetch = globalThis.fetch;
  const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'immich-client-'));
  const filePath = path.join(tempDir, 'image.jpg');
  await fs.writeFile(filePath, Buffer.from([1, 2, 3]));
  const requests: Array<{ path: string; method: string; body?: unknown }> = [];

  globalThis.fetch = (async (inputArg: RequestInfo | URL, initArg?: RequestInit) => {
    const url = new URL(String(inputArg));
    requests.push({ path: url.pathname, method: initArg?.method || 'GET', body: initArg?.body });
    if (url.pathname === '/api/albums/album-1') {
      expect(url.searchParams.get('withoutAssets')).toEqual('true');
      return jsonResponse({ id: 'album-1', albumName: 'Uploads' });
    }
    if (url.pathname === '/api/assets') {
      expect(initArg?.body instanceof FormData).toBeTrue();
      expect((initArg?.body as FormData).get('assetData')).toBeTruthy();
      return jsonResponse({ id: 'asset-1', status: 'created' });
    }
    if (url.pathname === '/api/albums/album-1/assets') {
      expect(String(initArg?.body)).toEqual(JSON.stringify({ ids: ['asset-1'] }));
      return jsonResponse([{ id: 'asset-1', success: true }]);
    }
    return jsonResponse({ message: 'not found' }, 404);
  }) as typeof globalThis.fetch;

  try {
    const client = new ImmichClient({ host: '127.0.0.1', port: 2283, apiKey: 'secret' });
    const result = await client.execute({ domain: 'immich', service: 'upload_file', target: {}, data: { path: filePath, album_id: 'album-1' } });

    expect(result.success).toBeTrue();
    expect(requests.map((requestArg) => `${requestArg.method} ${requestArg.path}`)).toEqual(['GET /api/albums/album-1', 'POST /api/assets', 'PUT /api/albums/album-1/assets']);
  } finally {
    globalThis.fetch = originalFetch;
    await fs.rm(tempDir, { recursive: true, force: true });
  }
});

tap.test('documents Immich local API support and unsupported TLS bypass', async () => {
  const localApi = immichProfile.metadata.localApi as { implemented: string[]; explicitUnsupported: string[] };

  expect(localApi.implemented.some((itemArg) => itemArg.includes('/api/server/about'))).toBeTrue();
  expect(localApi.explicitUnsupported.some((itemArg) => itemArg.includes('TLS certificate verification'))).toBeTrue();
});

const jsonResponse = (valueArg: unknown, statusArg = 200): Response => new Response(JSON.stringify(valueArg), {
  status: statusArg,
  headers: { 'content-type': 'application/json' },
});

export default tap.start();
