<?php

namespace App\Services\Customer\Wallet;

use App\Entities\CommonEntity;
use App\Entities\Customer\ClientEntity;
use App\Entities\PaymentEntity;
use App\Models\CommonModel;
use App\Services\Customer\CustomerService;
use RuntimeException;

abstract class WalletService extends CustomerService
{
    protected $title = "";
    protected $balanceField = "";
    protected function __construct(CommonModel $model)
    {
        parent::__construct($model);
        $this->addClassPaths('Wallet');
    }
    abstract protected function getClientBalance(ClientEntity $clientEntity): int;
    //기본기능
    protected function create_process(array $formDatas): CommonEntity
    {
        // 고객 정보
        if (empty($formDatas['clientinfo_uid'])) {
            throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: 고객정보(clientinfo_uid)가 전송되지 않았습니다.");
        }

        $clientEntity = service('customer_clientservice')->getEntity($formDatas['clientinfo_uid']);
        if (!$clientEntity instanceof ClientEntity) {
            throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$formDatas['clientinfo_uid']}에 해당하는 고객정보를 찾을수 없습니다.");
        }

        if (empty($formDatas['status'])) {
            throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: status가 전송되지 않았습니다.");
        }

        if (in_array($formDatas['status'], [STATUS['DEPOSIT'], STATUS['WITHDRAWAL']], true)) {
            if (!array_key_exists('amount', $formDatas)) {
                throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: amount가 전송되지 않았습니다.");
            }
            $formDatas['amount'] = (int) $formDatas['amount'];
            if ($formDatas['amount'] <= 0) {
                throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: amount는 1 이상이어야 합니다.");
            }
        }
        switch ($formDatas['status']) {
            case STATUS['DEPOSIT']:
                $entity = $this->deposit_process($clientEntity, $formDatas);
                break;
            case STATUS['WITHDRAWAL']:
                $entity = $this->withdrawal_process($clientEntity, $formDatas);
                break;
            default:
                throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: 지원하지 않는 status={$formDatas['status']}");
        }
        return $entity;
    }
    final protected function modify_process($entity, array $formDatas): CommonEntity
    {
        throw new RuntimeException("{$this->title}는 수정이 불가합니다.");
    }

    private function getFreshClientEntity(ClientEntity $clientEntity): ClientEntity
    {
        $fresh = service('customer_clientservice')->getEntity($clientEntity->getPK());

        if (!$fresh instanceof ClientEntity) {
            throw new RuntimeException(
                static::class . '->' . __FUNCTION__ . "에서 오류발생: 고객 재조회 실패"
            );
        }

        return $fresh;
    }

    //입금,쿠폰 충전 처리
    protected function deposit_process(ClientEntity $clientEntity, array $formDatas): CommonEntity
    {
        $amount = (int) ($formDatas['amount'] ?? 0);
        if ($amount <= 0) {
            throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$this->title}는 1 이상이어야 합니다.");
        }

        // 1) DB 원자 증가
        service('customer_clientservice')->increaseBalance($clientEntity->getPK(), $this->balanceField, $amount);

        // 2) ✅ 최신 잔액 재조회 (stale 방지)
        // balanceField를 기반으로 현재잔액 기록
        $formDatas['balance'] = $this->getClientBalance($this->getFreshClientEntity($clientEntity));

        // 3) wallet row 저장
        $entity = parent::create_process($formDatas);
        if (!$entity) {
            throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: 고객의 Wallet정보 생성에 실패하였습니다.");
        }
        return $entity;
    }

    protected function withdrawal_process(ClientEntity $clientEntity, array $formDatas): CommonEntity
    {
        $amount = (int) ($formDatas['amount'] ?? 0);
        if ($amount <= 0) {
            throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$this->title}는 1 이상이어야 합니다.");
        }

        // 1) DB 원자 차감(충분할 때만)
        $ok = service('customer_clientservice')->decreaseBalance($clientEntity->getPK(), $this->balanceField, $amount);

        if (!$ok) {
            throw new RuntimeException(sprintf(
                "{$this->title}이 부족합니다. (요청:%s원 / 현재:%s원)",
                number_format($amount),
                number_format((int) $this->getClientBalance($clientEntity)) // 메시지용
            ));
        }

        // 2) ✅ 최신 잔액 재조회 (stale 방지)
        // balanceField를 기반으로 현재잔액 기록
        $formDatas['balance'] = $this->getClientBalance($this->getFreshClientEntity($clientEntity));

        // 3) wallet row 저장
        $entity = parent::create_process($formDatas);
        if (!$entity) {
            throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: 고객의 Wallet정보 생성에 실패하였습니다.");
        }
        return $entity;
    }

    //결제관련 출금 처리(결제를 통해서만 호출되므로 action_init_process로 fields,rules 초기화 필요)
    public function withdrawalByPayment(PaymentEntity $paymentEntity, array $formDatas = []): CommonEntity
    {
        //고객 정보
        $clientEntity = service('customer_clientservice')->getEntity($paymentEntity->getClientInfoUid());
        if (!$clientEntity instanceof ClientEntity) {
            throw new RuntimeException(static::class . '->' . __FUNCTION__ . "에서 오류발생: {$paymentEntity->getClientInfoUid()}에 해당하는 고객정보를 찾을수 없습니다.");
        }
        $formDatas['clientinfo_uid'] = $paymentEntity->getClientInfoUid();
        $formDatas['title'] = $paymentEntity->getTitle();
        $formDatas['amount'] = $paymentEntity->getAmount();
        $formDatas['status'] = STATUS['WITHDRAWAL'];
        return $this->create_process($formDatas);
    }
}
