<?php

namespace App\Models\Sales;

use App\Models\Tenants\Tenant;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * 영업수수료 정산 모델
 *
 * @property int $id
 * @property int $tenant_id
 * @property int $management_id
 * @property string $payment_type
 * @property float $payment_amount
 * @property string $payment_date
 * @property string|null $first_payment_at 1차 납입완료일
 * @property string|null $first_partner_paid_at 1차 파트너 수당지급일
 * @property string|null $second_payment_at 2차 납입완료일
 * @property string|null $second_partner_paid_at 2차 파트너 수당지급일
 * @property string|null $first_subscription_at 첫 구독료 입금일 (매니저 수당 기준)
 * @property string|null $manager_paid_at 매니저 수당지급일
 * @property float $base_amount
 * @property float $partner_rate
 * @property float $manager_rate
 * @property float $partner_commission
 * @property float $manager_commission
 * @property string $scheduled_payment_date
 * @property string $status
 * @property string|null $actual_payment_date
 * @property int $partner_id
 * @property int|null $manager_user_id
 * @property string|null $notes
 * @property string|null $bank_reference
 * @property int|null $approved_by
 * @property \Carbon\Carbon|null $approved_at
 */
class SalesCommission extends Model
{
    use SoftDeletes;

    protected $table = 'sales_commissions';

    /**
     * 상태 상수
     */
    const STATUS_PENDING = 'pending';

    const STATUS_APPROVED = 'approved';

    const STATUS_PAID = 'paid';

    const STATUS_CANCELLED = 'cancelled';

    /**
     * 입금 구분 상수
     */
    const PAYMENT_DEPOSIT = 'deposit';

    const PAYMENT_BALANCE = 'balance';

    /**
     * 상태 라벨
     */
    public static array $statusLabels = [
        self::STATUS_PENDING => '대기',
        self::STATUS_APPROVED => '승인',
        self::STATUS_PAID => '지급완료',
        self::STATUS_CANCELLED => '취소',
    ];

    /**
     * 입금 구분 라벨
     */
    public static array $paymentTypeLabels = [
        self::PAYMENT_DEPOSIT => '계약금',
        self::PAYMENT_BALANCE => '잔금',
    ];

    protected $fillable = [
        'tenant_id',
        'management_id',
        'payment_type',
        'payment_amount',
        'payment_date',
        'first_payment_at',
        'first_partner_paid_at',
        'second_payment_at',
        'second_partner_paid_at',
        'first_subscription_at',
        'manager_paid_at',
        'base_amount',
        'partner_rate',
        'manager_rate',
        'partner_commission',
        'manager_commission',
        'scheduled_payment_date',
        'status',
        'actual_payment_date',
        'partner_id',
        'manager_user_id',
        'notes',
        'bank_reference',
        'approved_by',
        'approved_at',
        'referrer_partner_id',
        'referrer_rate',
        'referrer_commission',
        'first_referrer_paid_at',
        'second_referrer_paid_at',
    ];

    protected $casts = [
        'payment_amount' => 'decimal:2',
        'base_amount' => 'decimal:2',
        'partner_rate' => 'decimal:2',
        'manager_rate' => 'decimal:2',
        'partner_commission' => 'decimal:2',
        'manager_commission' => 'decimal:2',
        'payment_date' => 'date',
        'first_payment_at' => 'date',
        'first_partner_paid_at' => 'date',
        'second_payment_at' => 'date',
        'second_partner_paid_at' => 'date',
        'first_subscription_at' => 'date',
        'manager_paid_at' => 'date',
        'scheduled_payment_date' => 'date',
        'actual_payment_date' => 'date',
        'approved_at' => 'datetime',
        'referrer_rate' => 'decimal:2',
        'referrer_commission' => 'decimal:2',
        'first_referrer_paid_at' => 'date',
        'second_referrer_paid_at' => 'date',
    ];

    /**
     * 테넌트 관계
     */
    public function tenant(): BelongsTo
    {
        return $this->belongsTo(Tenant::class);
    }

    /**
     * 영업관리 관계
     */
    public function management(): BelongsTo
    {
        return $this->belongsTo(SalesTenantManagement::class, 'management_id');
    }

    /**
     * 영업파트너 관계
     */
    public function partner(): BelongsTo
    {
        return $this->belongsTo(SalesPartner::class, 'partner_id');
    }

    /**
     * 매니저(사용자) 관계
     */
    public function manager(): BelongsTo
    {
        return $this->belongsTo(User::class, 'manager_user_id');
    }

    /**
     * 상세 내역 관계
     */
    public function details(): HasMany
    {
        return $this->hasMany(SalesCommissionDetail::class, 'commission_id');
    }

    /**
     * 유치 영업파트너 관계
     */
    public function referrerPartner(): BelongsTo
    {
        return $this->belongsTo(SalesPartner::class, 'referrer_partner_id');
    }

    /**
     * 승인자 관계
     */
    public function approver(): BelongsTo
    {
        return $this->belongsTo(User::class, 'approved_by');
    }

    /**
     * 상태 라벨 Accessor
     */
    public function getStatusLabelAttribute(): string
    {
        return self::$statusLabels[$this->status] ?? $this->status;
    }

    /**
     * 입금 구분 라벨 Accessor
     */
    public function getPaymentTypeLabelAttribute(): string
    {
        return self::$paymentTypeLabels[$this->payment_type] ?? $this->payment_type;
    }

    /**
     * 총 수당액 Accessor
     */
    public function getTotalCommissionAttribute(): float
    {
        return $this->partner_commission + $this->manager_commission + $this->referrer_commission;
    }

    /**
     * 지급예정일 계산 (입금일 익월 10일)
     */
    public static function calculateScheduledPaymentDate(Carbon $paymentDate): Carbon
    {
        return $paymentDate->copy()->addMonth()->day(10);
    }

    /**
     * 승인 처리
     */
    public function approve(int $approverId): bool
    {
        if ($this->status !== self::STATUS_PENDING) {
            return false;
        }

        return $this->update([
            'status' => self::STATUS_APPROVED,
            'approved_by' => $approverId,
            'approved_at' => now(),
        ]);
    }

    /**
     * 지급완료 처리
     */
    public function markAsPaid(?string $bankReference = null): bool
    {
        if ($this->status !== self::STATUS_APPROVED) {
            return false;
        }

        return $this->update([
            'status' => self::STATUS_PAID,
            'actual_payment_date' => now()->format('Y-m-d'),
            'bank_reference' => $bankReference,
        ]);
    }

    /**
     * 승인취소 처리 (approved → pending)
     */
    public function unapprove(): bool
    {
        if ($this->status !== self::STATUS_APPROVED) {
            return false;
        }

        return $this->update([
            'status' => self::STATUS_PENDING,
            'approved_by' => null,
            'approved_at' => null,
        ]);
    }

    /**
     * 취소 처리
     */
    public function cancel(): bool
    {
        if ($this->status === self::STATUS_PAID) {
            return false;
        }

        return $this->update([
            'status' => self::STATUS_CANCELLED,
        ]);
    }

    /**
     * 대기 상태 스코프
     */
    public function scopePending(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_PENDING);
    }

    /**
     * 승인완료 스코프
     */
    public function scopeApproved(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_APPROVED);
    }

    /**
     * 지급완료 스코프
     */
    public function scopePaid(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_PAID);
    }

    /**
     * 특정 영업파트너 스코프
     */
    public function scopeForPartner(Builder $query, int $partnerId): Builder
    {
        return $query->where('partner_id', $partnerId);
    }

    /**
     * 특정 매니저 스코프
     */
    public function scopeForManager(Builder $query, int $managerUserId): Builder
    {
        return $query->where('manager_user_id', $managerUserId);
    }

    /**
     * 특정 월 지급예정 스코프
     */
    public function scopeForScheduledMonth(Builder $query, int $year, int $month): Builder
    {
        return $query->whereYear('scheduled_payment_date', $year)
            ->whereMonth('scheduled_payment_date', $month);
    }

    /**
     * 특정 기간 입금 스코프
     */
    public function scopePaymentDateBetween(Builder $query, string $startDate, string $endDate): Builder
    {
        return $query->whereBetween('payment_date', [$startDate, $endDate]);
    }

    // ========================================
    // 2단계 수당 지급 관련 메서드
    // ========================================

    /**
     * 1차 납입완료 처리
     */
    public function recordFirstPayment(?Carbon $paymentDate = null): bool
    {
        return $this->update([
            'first_payment_at' => $paymentDate ?? now(),
        ]);
    }

    /**
     * 1차 파트너 수당 지급 처리
     */
    public function recordFirstPartnerPaid(?Carbon $paidDate = null): bool
    {
        if (! $this->first_payment_at) {
            return false; // 1차 납입이 먼저 완료되어야 함
        }

        return $this->update([
            'first_partner_paid_at' => $paidDate ?? now(),
        ]);
    }

    /**
     * 2차 납입완료 처리
     */
    public function recordSecondPayment(?Carbon $paymentDate = null): bool
    {
        return $this->update([
            'second_payment_at' => $paymentDate ?? now(),
        ]);
    }

    /**
     * 2차 파트너 수당 지급 처리
     */
    public function recordSecondPartnerPaid(?Carbon $paidDate = null): bool
    {
        if (! $this->second_payment_at) {
            return false; // 2차 납입이 먼저 완료되어야 함
        }

        return $this->update([
            'second_partner_paid_at' => $paidDate ?? now(),
        ]);
    }

    /**
     * 첫 구독료 입금 기록 (매니저 수당 기준)
     */
    public function recordFirstSubscription(?Carbon $subscriptionDate = null): bool
    {
        return $this->update([
            'first_subscription_at' => $subscriptionDate ?? now(),
        ]);
    }

    /**
     * 매니저 수당 지급 처리
     */
    public function recordManagerPaid(?Carbon $paidDate = null): bool
    {
        if (! $this->first_subscription_at) {
            return false; // 첫 구독료 입금이 먼저 완료되어야 함
        }

        return $this->update([
            'manager_paid_at' => $paidDate ?? now(),
        ]);
    }

    /**
     * 1차 파트너 수당 지급예정일 (1차 납입일 익월 10일)
     */
    public function getFirstPartnerScheduledDateAttribute(): ?Carbon
    {
        if (! $this->first_payment_at) {
            return null;
        }

        return Carbon::parse($this->first_payment_at)->addMonth()->day(10);
    }

    /**
     * 2차 파트너 수당 지급예정일 (2차 납입일 익월 10일)
     */
    public function getSecondPartnerScheduledDateAttribute(): ?Carbon
    {
        if (! $this->second_payment_at) {
            return null;
        }

        return Carbon::parse($this->second_payment_at)->addMonth()->day(10);
    }

    /**
     * 매니저 수당 지급예정일 (첫 구독료 입금일 익월 10일)
     */
    public function getManagerScheduledDateAttribute(): ?Carbon
    {
        if (! $this->first_subscription_at) {
            return null;
        }

        return Carbon::parse($this->first_subscription_at)->addMonth()->day(10);
    }

    /**
     * 파트너 수당 1차 지급 완료 여부
     */
    public function isFirstPartnerPaid(): bool
    {
        return $this->first_partner_paid_at !== null;
    }

    /**
     * 파트너 수당 2차 지급 완료 여부
     */
    public function isSecondPartnerPaid(): bool
    {
        return $this->second_partner_paid_at !== null;
    }

    /**
     * 매니저 수당 지급 완료 여부
     */
    public function isManagerPaid(): bool
    {
        return $this->manager_paid_at !== null;
    }

    /**
     * 1차 유치수당 지급 처리
     */
    public function recordFirstReferrerPaid(?Carbon $paidDate = null): bool
    {
        if (! $this->referrer_partner_id) {
            return false;
        }

        return $this->update([
            'first_referrer_paid_at' => $paidDate ?? now(),
        ]);
    }

    /**
     * 2차 유치수당 지급 처리
     */
    public function recordSecondReferrerPaid(?Carbon $paidDate = null): bool
    {
        if (! $this->referrer_partner_id) {
            return false;
        }

        return $this->update([
            'second_referrer_paid_at' => $paidDate ?? now(),
        ]);
    }

    /**
     * 1차 유치수당 지급 완료 여부
     */
    public function isFirstReferrerPaid(): bool
    {
        return $this->first_referrer_paid_at !== null;
    }

    /**
     * 2차 유치수당 지급 완료 여부
     */
    public function isSecondReferrerPaid(): bool
    {
        return $this->second_referrer_paid_at !== null;
    }

    /**
     * 전체 수당 지급 완료 여부 (파트너 1차/2차 + 매니저 + 유치수당)
     */
    public function isFullyPaid(): bool
    {
        $basePaid = $this->isFirstPartnerPaid()
            && $this->isSecondPartnerPaid()
            && $this->isManagerPaid();

        if ($this->referrer_partner_id) {
            return $basePaid && $this->isFirstReferrerPaid() && $this->isSecondReferrerPaid();
        }

        return $basePaid;
    }
}
