<?php

require_once __DIR__ . '/../../../autoload/Domain/Finances/FakturowniaApiClient.php';

use Domain\Finances\FakturowniaApiClient;

class FakeFakturowniaApiClient extends FakturowniaApiClient
{
  public $calledPaths = [];
  public $responses = [];

  protected function request( $path, $query )
  {
    $this -> calledPaths[] = [ 'path' => $path, 'query' => $query ];

    if ( !isset( $this -> responses[ $path ] ) )
      return [ 'http_code' => 200, 'body' => '[]' ];

    return $this -> responses[ $path ];
  }
}

function run_fakturownia_api_client_tests()
{
  // AC-1: /invoices.json?income=no jest pytane jako primary source,
  // pusta odpowiedz /costs.json NIE konczy wczesniej i faktura 486639934 z /invoices.json trafia do wynikow.
  $client = new FakeFakturowniaApiClient( 'https://example', 'token', 100 );
  $client -> responses = [
    '/invoices.json' => [
      'http_code' => 200,
      'body' => json_encode( [
        'invoices' => [
          [
            'id' => 486639934,
            'number' => 'FV 100/04/2026',
            'kind' => 'vat',
            'income' => false,
            'issue_date' => '2026-04-05',
            'seller_name' => 'Dostawca Sp. z o.o.',
            'seller_tax_no' => '5252344567'
          ]
        ]
      ] )
    ],
    '/costs.json' => [ 'http_code' => 200, 'body' => '[]' ],
    '/expenses.json' => [ 'http_code' => 404, 'body' => '' ]
  ];

  $result = $client -> fetchCostDocuments( '2026-04-01', 1 );

  assert_true(
    count( $result ) === 1,
    'Expected faktura 486639934 to be returned from /invoices.json?income=no even when /costs.json is empty.'
  );
  assert_true(
    (string)$result[0]['id'] === '486639934',
    'Expected invoice id 486639934 in merged cost documents.'
  );

  $paths = array_map( function( $c ) { return $c['path']; }, $client -> calledPaths );
  assert_true(
    in_array( '/invoices.json', $paths, true ),
    'Expected /invoices.json to be queried for cost documents.'
  );
  assert_true(
    in_array( '/costs.json', $paths, true ),
    'Expected /costs.json to be queried as secondary source.'
  );
  assert_true(
    in_array( '/expenses.json', $paths, true ),
    'Expected /expenses.json to be queried as tertiary source (bug 05-04: empty /costs.json must not short-circuit).'
  );

  // AC-2: period=more + date_from + date_to sa wysylane, by API filtrowalo po issue_date.
  // Bez tego importer pobieralby wszystkie historyczne faktury i cron by sie zawiesil.
  $invoicesCall = null;
  foreach ( $client -> calledPaths as $call )
  {
    if ( $call['path'] === '/invoices.json' )
    {
      $invoicesCall = $call;
      break;
    }
  }
  assert_true( $invoicesCall !== null, 'Expected at least one call to /invoices.json.' );
  assert_true(
    ( $invoicesCall['query']['period'] ?? '' ) === 'more',
    'Expected period=more parameter so Fakturownia filters by date range server-side.'
  );
  assert_true(
    ( $invoicesCall['query']['date_from'] ?? '' ) === '2026-04-01',
    'Expected date_from to match startDate passed to fetchCostDocuments.'
  );
  assert_true(
    !empty( $invoicesCall['query']['date_to'] ?? '' ),
    'Expected date_to to be set (default: today) to complete the range filter.'
  );
  assert_true(
    ( $invoicesCall['query']['income'] ?? '' ) === 'no',
    'Expected income=no filter on /invoices.json for cost documents.'
  );

  // Dedup: ten sam id w /invoices.json i /costs.json trafia raz.
  $dedupClient = new FakeFakturowniaApiClient( 'https://example', 'token', 100 );
  $dedupClient -> responses = [
    '/invoices.json' => [
      'http_code' => 200,
      'body' => json_encode( [
        'invoices' => [
          [ 'id' => 111, 'number' => 'A', 'income' => false ],
          [ 'id' => 222, 'number' => 'B', 'income' => false ]
        ]
      ] )
    ],
    '/costs.json' => [
      'http_code' => 200,
      'body' => json_encode( [
        'costs' => [
          [ 'id' => 222, 'number' => 'B' ],
          [ 'id' => 333, 'number' => 'C' ]
        ]
      ] )
    ]
  ];

  $merged = $dedupClient -> fetchCostDocuments( '2026-04-01', 1 );
  $ids = array_map( function( $d ) { return (string)$d['id']; }, $merged );
  sort( $ids );
  assert_true(
    $ids === [ '111', '222', '333' ],
    'Expected merged cost documents to be deduplicated by id across endpoints.'
  );

  // Gdy wszystkie 3 sciezki zwroca HTTP >= 400, fetchCostDocuments rzuca wyjatek.
  $errorClient = new FakeFakturowniaApiClient( 'https://example', 'token', 100 );
  $errorClient -> responses = [
    '/invoices.json' => [ 'http_code' => 500, 'body' => '' ],
    '/costs.json' => [ 'http_code' => 500, 'body' => '' ],
    '/expenses.json' => [ 'http_code' => 500, 'body' => '' ]
  ];

  $threw = false;
  try
  {
    $errorClient -> fetchCostDocuments( '2026-04-01', 1 );
  }
  catch ( \Throwable $e )
  {
    $threw = true;
  }
  assert_true(
    $threw,
    'Expected fetchCostDocuments to throw when all endpoints fail with HTTP errors.'
  );

  // Gdy wszystkie 3 sciezki zwroca pusta liste z HTTP 200, zwracamy [] (nie wyjatek).
  $emptyClient = new FakeFakturowniaApiClient( 'https://example', 'token', 100 );
  $emptyClient -> responses = [
    '/invoices.json' => [ 'http_code' => 200, 'body' => '[]' ],
    '/costs.json' => [ 'http_code' => 200, 'body' => '[]' ],
    '/expenses.json' => [ 'http_code' => 200, 'body' => '[]' ]
  ];
  $emptyResult = $emptyClient -> fetchCostDocuments( '2026-04-01', 1 );
  assert_true(
    is_array( $emptyResult ) && count( $emptyResult ) === 0,
    'Expected empty array when all endpoints return HTTP 200 with empty lists.'
  );
}
