<?php

namespace App\Services;

use App\Laravue\Models\User;
use Illuminate\Support\Facades\Log;

/**
 * PAY.JP Platform (Payouts型) 連携サービス
 *
 * テナント管理とPayouts型決済を扱う。
 * PAY.JP Platform API: https://pay.jp/docs/platform
 */
class PayjpPlatformService
{
    public function __construct()
    {
        \Payjp\Payjp::setApiKey(config('payjp.secret_key'));
    }

    /**
     * テナント（オーナー）を作成
     *
     * オーナーの口座情報をPAY.JP Platformにテナントとして登録する。
     * PAY.JPからオーナーの口座へ直接振込が行われるようになる。
     *
     * @param User $owner オーナーユーザー
     * @return string tenant ID
     * @throws \Exception
     */
    public function createTenant(User $owner): string
    {
        if ($owner->payjp_tenant_id) {
            Log::info("PayjpPlatformService: テナント既存 owner_id={$owner->id}, tenant_id={$owner->payjp_tenant_id}");
            return $owner->payjp_tenant_id;
        }

        if (!$owner->bank_code || !$owner->bank_branch_code || !$owner->bank_account_number) {
            throw new \Exception("オーナーの口座情報が不足しています (owner_id: {$owner->id})");
        }

        $tenant = \Payjp\Tenant::create([
            'name' => $owner->full_name ?? $owner->name,
            'platform_fee_rate' => '0', // 固定額を使うので料率は0
            'bank_account_holder_name' => $owner->bank_holder_name,
            'bank_code' => $owner->bank_code,
            'bank_branch_code' => $owner->bank_branch_code,
            'bank_account_type' => $this->normalizeBankAccountType($owner->bank_account_type),
            'bank_account_number' => $owner->bank_account_number,
        ]);

        $owner->update(['payjp_tenant_id' => $tenant->id]);

        Log::info("PayjpPlatformService: テナント作成 owner_id={$owner->id}, tenant_id={$tenant->id}");

        return $tenant->id;
    }

    /**
     * テナント情報を更新（口座変更時）
     *
     * @param User $owner
     * @return void
     * @throws \Exception
     */
    public function updateTenant(User $owner): void
    {
        if (!$owner->payjp_tenant_id) {
            throw new \Exception("テナントが未登録です (owner_id: {$owner->id})");
        }

        $tenant = \Payjp\Tenant::retrieve($owner->payjp_tenant_id);
        $tenant->bank_account_holder_name = $owner->bank_holder_name;
        $tenant->bank_code = $owner->bank_code;
        $tenant->bank_branch_code = $owner->bank_branch_code;
        $tenant->bank_account_type = $this->normalizeBankAccountType($owner->bank_account_type);
        $tenant->bank_account_number = $owner->bank_account_number;
        $tenant->save();

        Log::info("PayjpPlatformService: テナント更新 owner_id={$owner->id}, tenant_id={$owner->payjp_tenant_id}");
    }

    /**
     * DB の bank_account_type 値を PAY.JP の値 (normal/checking) に正規化する。
     *
     * 現状の保存値は 0=普通 / 1=当座 の数値だが、過去には文字列 '普通' / '当座' で
     * 保存されていた時期があるため両形式に対応する。'当座' または 1 のときだけ
     * 'checking'、それ以外 (空・null・'普通'・0) は 'normal'。
     */
    private function normalizeBankAccountType($value): string
    {
        if ($value === '当座' || (string) $value === '1') {
            return 'checking';
        }
        return 'normal';
    }

    /**
     * Payouts型決済を作成（レンタル決済時にオーナーへの報酬分を振り分け）
     *
     * 通常の決済にテナントIDとプラットフォーム手数料を指定することで、
     * オーナーへの振り分けが自動的に行われる。
     *
     * @param string $customerId PAY.JP顧客ID（レンタルユーザー）
     * @param string|null $cardId カードID
     * @param int $amount 決済総額
     * @param int $platformFee KIREI取り分（= amount - reward_amount）
     * @param string $tenantId PAY.JPテナントID（オーナー）
     * @param string $description 説明
     * @return \Payjp\Charge
     * @throws \Exception
     */
    public function createChargeWithPayout(
        string $customerId,
        ?string $cardId,
        int $amount,
        int $platformFee,
        string $tenantId,
        string $description = ''
    ) {
        $params = [
            'customer' => $customerId,
            'amount' => $amount,
            'currency' => 'jpy',
            'platform_fee' => $platformFee,
            'tenant' => $tenantId,
            'description' => $description,
        ];

        if ($cardId) {
            $params['card'] = $cardId;
        }

        $charge = \Payjp\Charge::create($params);

        Log::info("PayjpPlatformService: Payouts決済作成 charge_id={$charge->id}, amount={$amount}, platform_fee={$platformFee}, tenant_id={$tenantId}");

        return $charge;
    }

    /**
     * テナントを削除
     *
     * @param User $owner
     * @return void
     */
    public function deleteTenant(User $owner): void
    {
        if (!$owner->payjp_tenant_id) {
            return;
        }

        try {
            $tenant = \Payjp\Tenant::retrieve($owner->payjp_tenant_id);
            $tenant->delete();
        } catch (\Exception $e) {
            Log::warning("PayjpPlatformService: テナント削除失敗 owner_id={$owner->id}, error={$e->getMessage()}");
        }

        $owner->update(['payjp_tenant_id' => null]);

        Log::info("PayjpPlatformService: テナント削除 owner_id={$owner->id}");
    }
}
