import { test, expect, Page } from '@playwright/test';

const LOGIN_URL = 'http://localhost:3000/login';
const API_URL = 'http://localhost:8000/api';
const USERNAME = 'admin';
const PASSWORD = 'admin123';

/** ログインしてトークンを localStorage にセット */
async function loginViaUI(page: Page) {
  await page.goto(LOGIN_URL);
  await page.fill('#username', USERNAME);
  await page.fill('#password', PASSWORD);
  await page.click('button[type="submit"]');
  // ログイン後 /allocation にリダイレクトされるのを待つ
  await page.waitForURL('**/allocation', { timeout: 15000 });
}

// ===== D-4: IsAuthenticated が有効か =====
test.describe('D-4: IsAuthenticated', () => {
  test('未認証で API にアクセスすると 401 が返る', async ({ request }) => {
    const res = await request.get(`${API_URL}/fields/`);
    expect(res.status()).toBe(401);
  });

  test('未認証でフロントにアクセスするとログイン画面にリダイレクト', async ({ page }) => {
    await page.goto('http://localhost:3000/allocation');
    // API が 401 を返すので、フロントがログイン画面に遷移するはず
    await page.waitForURL('**/login', { timeout: 10000 });
    await expect(page.locator('text=KeinaSystem')).toBeVisible();
  });
});

// ===== ログイン → 作付計画画面 =====
test.describe('ログイン → 作付計画画面', () => {
  test('ログインして作付計画画面が表示される', async ({ page }) => {
    await loginViaUI(page);
    // allocation ページにいることを確認
    expect(page.url()).toContain('/allocation');
    // 圃場のデータが読み込まれるのを待つ（テーブルまたはリストが表示されるはず）
    await page.waitForTimeout(2000);
    // ページ内に何かしらのコンテンツがある
    const body = await page.textContent('body');
    expect(body).toBeTruthy();
  });
});

// ===== A-8: 圃場詳細の共済/中山間情報表示 =====
test.describe('A-8: 圃場詳細 共済/中山間情報', () => {
  test('共済・中山間の両方が紐づく圃場で情報が表示される', async ({ page }) => {
    await loginViaUI(page);
    // Field ID 8 (口神　ハウス南) は kyosai=1, chusankan=1
    await page.goto('http://localhost:3000/fields/8');
    await page.waitForLoadState('networkidle');

    // 共済情報セクション
    await expect(page.locator('text=共済情報')).toBeVisible();
    // テーブルヘッダが表示される
    await expect(page.locator('text=耕地-分筆')).toBeVisible();
    await expect(page.locator('text=漢字地名')).toBeVisible();
    // 「紐づけられた共済区画はありません」が表示されないこと
    await expect(page.locator('text=紐づけられた共済区画はありません')).not.toBeVisible();

    // 中山間情報セクション
    await expect(page.locator('text=中山間情報')).toBeVisible();
    await expect(page.locator('text=所在地')).toBeVisible();
    // 「紐づけられた中山間区画はありません」が表示されないこと
    await expect(page.locator('text=紐づけられた中山間区画はありません')).not.toBeVisible();
  });

  test('共済のみ紐づく圃場で共済情報が表示される', async ({ page }) => {
    await loginViaUI(page);
    // Field ID 3 (おまけ) は kyosai=1, chusankan=0
    await page.goto('http://localhost:3000/fields/3');
    await page.waitForLoadState('networkidle');

    await expect(page.locator('text=共済情報')).toBeVisible();
    await expect(page.locator('text=紐づけられた共済区画はありません')).not.toBeVisible();
    await expect(page.locator('text=紐づけられた中山間区画はありません')).toBeVisible();
  });
});

// ===== E-1: PDF帳票フォーマット再設計 =====
test.describe('E-1: PDF帳票', () => {
  test('共済PDF が 200 で返る（表形式テンプレート）', async ({ page }) => {
    await loginViaUI(page);
    const token = await page.evaluate(() => localStorage.getItem('accessToken'));
    const res = await page.request.get(`${API_URL}/reports/kyosai/2025/`, {
      headers: { Authorization: `Bearer ${token}` },
    });
    expect(res.status()).toBe(200);
    expect(res.headers()['content-type']).toContain('application/pdf');
  });

  test('中山間PDF が 200 で返る（表形式テンプレート）', async ({ page }) => {
    await loginViaUI(page);
    const token = await page.evaluate(() => localStorage.getItem('accessToken'));
    const res = await page.request.get(`${API_URL}/reports/chusankan/2025/`, {
      headers: { Authorization: `Bearer ${token}` },
    });
    expect(res.status()).toBe(200);
    expect(res.headers()['content-type']).toContain('application/pdf');
  });

  test('帳票画面からPDFダウンロードリンクが表示される', async ({ page }) => {
    await loginViaUI(page);
    await page.goto('http://localhost:3000/reports');
    await page.waitForLoadState('networkidle');
    // 帳票画面が表示される
    const body = await page.textContent('body');
    expect(body).toBeTruthy();
  });
});

// ===== E-1c: 中山間マスタ 17フィールド =====
test.describe('E-1c: 中山間マスタ拡張', () => {
  test('中山間 API が 17 フィールドを返す', async ({ page }) => {
    await loginViaUI(page);
    const token = await page.evaluate(() => localStorage.getItem('accessToken'));
    // Field ID 8 は chusankan=1
    const res = await page.request.get(`${API_URL}/fields/8/`, {
      headers: { Authorization: `Bearer ${token}` },
    });
    expect(res.status()).toBe(200);
    const data = await res.json();
    const ch = data.chusankan_fields[0];
    expect(ch).toBeDefined();
    // 新フィールドが存在する
    expect(ch).toHaveProperty('manager');
    expect(ch).toHaveProperty('owner');
    expect(ch).toHaveProperty('planting_area');
    expect(ch).toHaveProperty('original_crop');
    expect(ch).toHaveProperty('slope');
    expect(ch).toHaveProperty('base_amount');
    expect(ch).toHaveProperty('branch_num');
    expect(ch).toHaveProperty('land_type');
  });

  test('共済マスタの面積が 0 でない', async ({ page }) => {
    await loginViaUI(page);
    const token = await page.evaluate(() => localStorage.getItem('accessToken'));
    // Field ID 3 (おまけ) は kyosai=1
    const res = await page.request.get(`${API_URL}/fields/3/`, {
      headers: { Authorization: `Bearer ${token}` },
    });
    const data = await res.json();
    const k = data.kyosai_fields[0];
    expect(k).toBeDefined();
    expect(k.area).toBeGreaterThan(0);
  });
});

// ===== C-2: 共済マスタ unique 制約 =====
test.describe('C-2: 共済マスタ unique 制約 (k_num, s_num)', () => {
  test('同じ k_num + s_num の重複登録が拒否される', async ({ page }) => {
    await loginViaUI(page);
    const token = await page.evaluate(() => localStorage.getItem('accessToken'));

    // まずテスト用データを作成
    const createRes = await page.request.post(`${API_URL}/fields/kyosai/`, {
      headers: {
        Authorization: `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
      data: {
        k_num: 'TEST99',
        s_num: '1',
        kanji_name: 'テスト区画',
        address: 'テスト住所',
        area: 1000,
      },
    });

    // 作成成功 or 既に存在する場合
    if (createRes.status() === 201) {
      // 同じ k_num + s_num で再度作成 → 拒否されるべき
      const dupRes = await page.request.post(`${API_URL}/fields/kyosai/`, {
        headers: {
          Authorization: `Bearer ${token}`,
          'Content-Type': 'application/json',
        },
        data: {
          k_num: 'TEST99',
          s_num: '1',
          kanji_name: 'テスト区画2',
          address: 'テスト住所2',
          area: 2000,
        },
      });
      // 400 (validation error) が返るべき
      expect(dupRes.status()).toBe(400);

      // クリーンアップ: テストデータ削除
      const created = await createRes.json();
      await page.request.delete(`${API_URL}/fields/kyosai/${created.id}/`, {
        headers: { Authorization: `Bearer ${token}` },
      });
    }
  });
});
