<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

/**
 * 売上集計結果モデル - earnings_summaryテーブル
 * 
 * SHJ-9で作成される日次・月次・年次の売上集計データを管理
 */
class EarningsSummary extends Model
{
    /**
     * テーブル名
     *
     * @var string
     */
    protected $table = 'earnings_summary';

    /**
     * プライマリキー
     *
     * @var string
     */
    protected $primaryKey = 'earnings_summary_id';

    /**
     * 一括代入可能な属性
     *
     * @var array
     */
    protected $fillable = [
        'park_id',                           // 駐輪場ID
        'summary_type',                      // 集計区分
        'summary_start_date',                // 集計開始日
        'summary_end_date',                  // 集計終了日
        'earnings_date',                     // 売上日
        'psection_id',                       // 車種区分ID
        'usertype_subject1',                 // 規格
        'enable_months',                     // 期間(月数)
        'regular_new_count',                 // 期間件数
        'regular_new_amount',                // 期間金額
        'regular_new_reduction_count',       // 期間成免件数
        'regular_new_reduction_amount',      // 期間成免金額
        'regular_update_count',              // 更新件数
        'regular_update_amount',             // 更新金額
        'regular_update_reduction_count',    // 更新成免件数
        'regular_update_reduction_amount',   // 更新成免金額
        'lumpsum_count',                     // 一時金件数
        'lumpsum',                           // 一時金
        'refunds',                           // 解時返戻金
        'other_income',                      // 分別収入
        'other_spending',                    // 分別支出
        'reissue_count',                     // 発行件数
        'reissue_amount',                    // 発行金額
        'summary_note',                      // 計備考
        'created_at',                        // 登録日時
        'updated_at',                        // 更新日時
        'operator_id'                        // 新法・ページID
    ];

    /**
     * キャストする属性
     *
     * @var array
     */
    protected $casts = [
        'earnings_summary_id' => 'integer',
        'park_id' => 'integer',
        'psection_id' => 'integer',
        'enable_months' => 'integer',
        'regular_new_count' => 'integer',
        'regular_new_amount' => 'decimal:2',
        'regular_new_reduction_count' => 'integer',
        'regular_new_reduction_amount' => 'decimal:2',
        'regular_update_count' => 'integer',
        'regular_update_amount' => 'decimal:2',
        'regular_update_reduction_count' => 'integer',
        'regular_update_reduction_amount' => 'decimal:2',
        'lumpsum_count' => 'integer',
        'lumpsum' => 'decimal:2',
        'refunds' => 'decimal:2',
        'other_income' => 'decimal:2',
        'other_spending' => 'decimal:2',
        'reissue_count' => 'integer',
        'reissue_amount' => 'decimal:2',
        'operator_id' => 'integer',
        'summary_start_date' => 'date',
        'summary_end_date' => 'date',
        'earnings_date' => 'date',
        'created_at' => 'datetime',
        'updated_at' => 'datetime'
    ];

    /**
     * 日付属性
     *
     * @var array
     */
    protected $dates = [
        'summary_start_date',
        'summary_end_date',
        'earnings_date',
        'created_at',
        'updated_at'
    ];

    /**
     * 集計タイプの定数
     */
    const TYPE_DAILY = '日次';
    const TYPE_MONTHLY = '月次';
    const TYPE_YEARLY = '年次';

    /**
     * 駐輪場との関連
     * 
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function park()
    {
        return $this->belongsTo(Park::class, 'park_id', 'park_id');
    }

    /**
     * 車種区分との関連
     * 
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function psection()
    {
        return $this->belongsTo(Psection::class, 'psection_id', 'psection_id');
    }

    /**
     * 指定期間の売上集計データを取得
     * 
     * @param int $parkId 駐輪場ID
     * @param string $startDate 開始日
     * @param string $endDate 終了日
     * @param string|null $summaryType 集計タイプ
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public static function getEarningsByPeriod(int $parkId, string $startDate, string $endDate, ?string $summaryType = null)
    {
        $query = self::where('park_id', $parkId)
            ->whereBetween('earnings_date', [$startDate, $endDate]);
            
        if ($summaryType) {
            $query->where('summary_type', $summaryType);
        }
        
        return $query->with(['park', 'psection'])
            ->orderBy('earnings_date')
            ->orderBy('psection_id')
            ->get();
    }

    /**
     * 駐輪場別の売上合計を取得
     * 
     * @param int $parkId 駐輪場ID
     * @param string $startDate 開始日
     * @param string $endDate 終了日
     * @return array 売上合計データ
     */
    public static function getEarningsTotalByPark(int $parkId, string $startDate, string $endDate): array
    {
        $result = self::where('park_id', $parkId)
            ->whereBetween('earnings_date', [$startDate, $endDate])
            ->selectRaw('
                SUM(regular_new_count) as total_new_count,
                SUM(regular_new_amount) as total_new_amount,
                SUM(regular_update_count) as total_update_count,
                SUM(regular_update_amount) as total_update_amount,
                SUM(lumpsum_count) as total_lumpsum_count,
                SUM(lumpsum) as total_lumpsum,
                SUM(refunds) as total_refunds,
                SUM(reissue_count) as total_reissue_count,
                SUM(reissue_amount) as total_reissue_amount
            ')
            ->first();
            
        return $result ? $result->toArray() : [];
    }

    /**
     * 最新の集計日を取得
     * 
     * @param int|null $parkId 駐輪場ID（省略時は全体）
     * @param string|null $summaryType 集計タイプ
     * @return string|null 最新集計日
     */
    public static function getLatestEarningsDate(?int $parkId = null, ?string $summaryType = null): ?string
    {
        $query = self::query();
        
        if ($parkId) {
            $query->where('park_id', $parkId);
        }
        
        if ($summaryType) {
            $query->where('summary_type', $summaryType);
        }
        
        $latest = $query->max('earnings_date');
        
        return $latest ? Carbon::parse($latest)->format('Y-m-d') : null;
    }

    /**
     * 期間の売上データを削除
     * 
     * @param int $parkId 駐輪場ID
     * @param string $startDate 開始日
     * @param string $endDate 終了日
     * @param string|null $summaryType 集計タイプ
     * @return int 削除件数
     */
    public static function deleteEarningsByPeriod(int $parkId, string $startDate, string $endDate, ?string $summaryType = null): int
    {
        $query = self::where('park_id', $parkId)
            ->where('summary_start_date', $startDate)
            ->where('summary_end_date', $endDate);
            
        if ($summaryType) {
            $query->where('summary_type', $summaryType);
        }
        
        return $query->delete();
    }

    /**
     * 売上集計データの作成
     * 
     * @param array $data 売上データ
     * @return EarningsSummary 作成されたモデル
     */
    public static function createEarningsSummary(array $data): EarningsSummary
    {
        $defaultData = [
            'regular_new_count' => 0,
            'regular_new_amount' => 0.00,
            'regular_new_reduction_count' => 0,
            'regular_new_reduction_amount' => 0.00,
            'regular_update_count' => 0,
            'regular_update_amount' => 0.00,
            'regular_update_reduction_count' => 0,
            'regular_update_reduction_amount' => 0.00,
            'lumpsum_count' => 0,
            'lumpsum' => 0.00,
            'refunds' => 0.00,
            'other_income' => 0.00,
            'other_spending' => 0.00,
            'reissue_count' => 0,
            'reissue_amount' => 0.00,
            'operator_id' => 0
        ];
        
        $mergedData = array_merge($defaultData, $data);
        
        return self::create($mergedData);
    }

    /**
     * 売上合計の計算
     * 
     * @return float 売上合計
     */
    public function getTotalEarningsAttribute(): float
    {
        return $this->regular_new_amount + 
               $this->regular_update_amount + 
               $this->lumpsum + 
               $this->reissue_amount +
               $this->other_income -
               $this->other_spending -
               $this->refunds;
    }

    /**
     * 文字列表現
     * 
     * @return string
     */
    public function __toString(): string
    {
        return sprintf(
            'EarningsSummary[ID:%d, Park:%d, Type:%s, Date:%s]',
            $this->earnings_summary_id,
            $this->park_id,
            $this->summary_type,
            $this->earnings_date ? $this->earnings_date->format('Y-m-d') : 'N/A'
        );
    }
}
