<?php

namespace app\admin\service\coupon;

use app\model\Coupon;
use app\model\CouponDetail;
use app\model\SysSerial;
use support\Db;
use support\exception\BusinessException;
use support\Log;

class CouponDetailService
{
    /**
     * @Desc 手动发券
     * @Author Gorden
     * @Date 2024/8/27 9:57
     *
     * @param $params
     * @return void
     * @throws BusinessException
     */
    public static function customSendCoupon($params)
    {
        $gettype = 'SEND';
        if (!empty($params['gettype'])) {
            $gettype = $params['gettype'];
        }
        try {
            CouponDetail::insert([
                'coupon_detail_id' => 'CUDT' . date("ymdHi") . random_string(4, 'up'),
                'join_detail_coupon_id' => $params['coupon_id'],
                'join_coupon_detail_member_id' => $params['member_id'],
                'coupon_detail_status' => 'ACTIVED',
                'coupon_detail_gain_datetime' => $params['coupon_detail_gain_datetime'],
                'coupon_detail_deadline_datetime' => $params['coupon_detail_deadline_datetime'],
                'coupon_detail_period_num' => $params['coupon_detail_period_num'] ?? 0,
                'coupon_detail_extend_json' => json_encode(['gettype' => $gettype, 'order_id' => $params['order_id'] ?? '']),
                'coupon_detail_addtimes' => time(),
            ]);
        } catch (\Exception $e) {
            throw new BusinessException('写入优惠券失败');
        }
    }

    public static function customSendCouponHave($params)
    {
        $gettype = 'SEND';
        if (!empty($params['gettype'])) {
            $gettype = $params['gettype'];
        }
        try {
            CouponDetail::where('join_detail_coupon_id', $params['coupon_id'])
                ->whereIn('coupon_detail_status', ['INIT', 'PENDING'])
                ->limit($params['chooseCouponNbr'])
                ->update([
                    'join_coupon_detail_member_id' => $params['member_id'],
                    'coupon_detail_gain_datetime' => $params['coupon_detail_gain_datetime'],
                    'coupon_detail_deadline_datetime' => $params['coupon_detail_deadline_datetime'],
                    'coupon_detail_extend_json' => json_encode(['gettype' => $gettype, 'order_id' => $params['order_id'] ?? '']),
                    'coupon_detail_period_num' => $params['coupon_detail_period_num'] ?? 0,
                    'coupon_detail_status' => 'ACTIVED',
                    'coupon_detail_addtimes' => time()
                ]);
        } catch (\Exception $e) {
            throw new BusinessException('写入优惠券失败');
        }
    }

    /**
     * @Desc 发周期优惠券 - 没有发行数量
     * @Author Gorden
     * @Date 2024/9/27 13:44
     *
     * @param $params
     * @return void
     */
    public static function sendPeriodCoupon($params)
    {
        Db::beginTransaction();
        try {
            $coupon = Coupon::where('coupon_id', $params['coupon_id'])->first();
            if ($coupon->coupon_is_period != 'Y') {
                return;
            }
            $detailCount = -1;
            if ($coupon->coupon_number > 0) {
                $detailCount = CouponDetail::where('join_detail_coupon_id', $params['coupon_id'])->whereIn('coupon_detail_status', ['INIT', 'PENDING'])->count();
            }
            $periodJson = json_decode($coupon->coupon_period_json, true);
            if ($detailCount != -1 && $detailCount - $periodJson['nbr'] < 0) {
                throw new BusinessException("优惠券余量不足");
            }
            $periodJson['now_nbr'] = 1;
            // 手动发券会传来时间
            $periodJson['gain_datetime'] = $params['coupon_detail_gain_datetime'] ?? date('Y-m-d H:i:s');
            if (!empty($periodJson['nbr'])) {
                for ($i = 0; $i < $periodJson['nbr']; $i++) {
                    $periodParams = self::generatePeriod($periodJson);
                    $periodParams['gettype'] = $params['gettype'] ?? '';
                    $periodParams['order_id'] = $params['order_id'] ?? '';
                    $periodParams['coupon_id'] = $params['coupon_id'];
                    $periodParams['member_id'] = $params['member_id'];
                    $periodParams['coupon_detail_period_num'] = $periodJson['now_nbr'];
                    if ($detailCount > 0) {
                        $periodParams['chooseCouponNbr'] = 1;
                        self::sendPeriodCouponHave($periodParams);
                    } else {
                        self::sendPeriodCouponNoLimit($periodParams);
                    }

                    $periodJson['now_nbr'] += 1;
                }
            }
            Db::commit();
        } catch (BusinessException $e) {
            Db::rollBack();
            Log::error("发券失败:" . $e->getMessage());
            throw new BusinessException($e->getMessage());
        } catch (\Exception $e) {
            Db::rollBack();
            Log::error("发券失败:" . $e->getMessage());
            throw new BusinessException("优惠券发放失败");
        }
    }

    /**
     * @Desc 有发行数量
     * @Author Gorden
     * @Date 2024/9/27 13:45
     *
     * @param $params
     * @return void
     */
    public static function sendPeriodCouponHave($params)
    {
        $gettype = 'SEND';
        if (!empty($params['gettype'])) {
            $gettype = $params['gettype'];
        }
        try {
            CouponDetail::where('join_detail_coupon_id', $params['coupon_id'])
                ->whereIn('coupon_detail_status', ['INIT', 'PENDING'])
                ->limit($params['chooseCouponNbr'])
                ->update([
                    'join_coupon_detail_member_id' => $params['member_id'],
                    'coupon_detail_gain_datetime' => $params['coupon_detail_gain_datetime'],
                    'coupon_detail_deadline_datetime' => $params['coupon_detail_deadline_datetime'],
                    'coupon_detail_extend_json' => json_encode(['gettype' => $gettype, 'order_id' => $params['order_id'] ?? '']),
                    'coupon_detail_period_num' => $params['coupon_detail_period_num'] ?? 0,
                    'coupon_detail_status' => 'ACTIVED',
                    'coupon_detail_addtimes' => time()
                ]);
        } catch (\Exception $e) {
            dump($e->getMessage());
            throw new BusinessException('写入优惠券失败');
        }
    }

    /**
     * @Desc 发行量不限
     * @Author Gorden
     * @Date 2024/9/27 16:19
     *
     * @param $params
     * @return void
     * @throws BusinessException
     */
    public static function sendPeriodCouponNoLimit($params)
    {
        $gettype = 'SEND';
        if (!empty($params['gettype'])) {
            $gettype = $params['gettype'];
        }
        try {
            CouponDetail::insert([
                'coupon_detail_id' => 'CUDT' . date("ymdHi") . random_string(4, 'up'),
                'join_detail_coupon_id' => $params['coupon_id'],
                'join_coupon_detail_member_id' => $params['member_id'],
                'coupon_detail_status' => 'ACTIVED',
                'coupon_detail_gain_datetime' => $params['coupon_detail_gain_datetime'],
                'coupon_detail_deadline_datetime' => $params['coupon_detail_deadline_datetime'],
                'coupon_detail_period_num' => $params['coupon_detail_period_num'] ?? 0,
                'coupon_detail_extend_json' => json_encode(['gettype' => $gettype, 'order_id' => $params['order_id'] ?? '']),
                'coupon_detail_addtimes' => time(),
            ]);
        } catch (\Exception $e) {
            throw new BusinessException('写入优惠券失败');
        }
    }

    /**
     * @Desc
     * @Author Gorden
     * @Date 2024/9/27 13:54
     *
     * @param $periodJson
     * @return array
     */
    public static function generatePeriod($periodJson)
    {
        // 当前第几期
        $now_nbr = $periodJson['now_nbr'];
        $params = [];
        if ($periodJson['unit'] == 'day') {
            $val = $periodJson['val'] - 1;
            if ($val < 1) {
                if ($now_nbr == 1) {
                    $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime($periodJson['gain_datetime']));
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime($periodJson['gain_datetime']));
                } else {
                    $now_nbr -= 1;
                    $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime($periodJson['gain_datetime'] . "+" . $now_nbr . ' day'));
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime($periodJson['gain_datetime'] . "+" . $now_nbr . ' day'));
                }
            } else {
                if ($now_nbr == 1) {
                    $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime($periodJson['gain_datetime']));
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime($periodJson['gain_datetime'] . "+" . $val . ' day'));
                } else {
                    $now_nbr -= 1;
                    $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime($periodJson['gain_datetime'] . "+" . ((($val + 1) * $now_nbr)) . " day"));
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime($periodJson['gain_datetime'] . "+" . ((($val + 1) * $now_nbr) + $val) . " day"));
                }
            }
        } elseif ($periodJson['unit'] == 'week') {
            $val = $periodJson['val'] - 1;
            // 选的日期的周一距离今周周一是几个周
            $timestamp = strtotime($periodJson['gain_datetime']);
            $gainWeekDay = date("w", $timestamp);
            $gainWeekAdd = date("w", $gainWeekDay) == 1 ? 0 : 1 - $gainWeekDay;
            $gainMonday = date("Y-m-d 00:00:00", strtotime("$gainWeekAdd days", $timestamp));
            $nowMonday = date('Y-m-d 00:00:00', strtotime('this week Monday'));

            $interval = (new \DateTime(date($gainMonday)))->diff(new \DateTime($nowMonday));
            $weekCut = $interval->days / 7;
            if (strtotime($periodJson['gain_datetime']) < time() && $weekCut > 0) {
                $weekCut = -$weekCut;
            }
            if ($val < 1) {
                if ($now_nbr == 1) {
                    $params['coupon_detail_gain_datetime'] = $gainMonday;
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime($gainMonday . "+6 days"));
                } else {
                    $now_nbr -= 1;
                    $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d 00:00:00', strtotime('this week Monday')) . "+" . ($now_nbr + $weekCut) . ' week'));
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d 23:59:59', strtotime('this week Sunday')) . "+" . ($now_nbr + $weekCut) . ' week'));
                }
            } else {
                if ($now_nbr == 1) {
                    $params['coupon_detail_gain_datetime'] = $gainMonday;
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d 23:59:59', strtotime('this week Sunday')) . "+" . ($val + $weekCut) . ' week'));
                } else {
                    $now_nbr -= 1;
                    $params['coupon_detail_gain_datetime'] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d 00:00:00', strtotime('this week Monday')) . "+" . ((($val + 1) * $now_nbr) + $weekCut) . ' week'));
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d 23:59:59', strtotime('this week Sunday')) . "+" . ((($val + 1) * $now_nbr) + $val + $weekCut) . ' week'));
                }
            }
        } elseif ($periodJson['unit'] == 'month') {
            $val = $periodJson['val'] - 1;
            // 选的日期的1号距离今月1号是几个月
            $interval = (new \DateTime(date('Y-m-02 00:00:00', strtotime($periodJson['gain_datetime']))))->diff(new \DateTime(date('Y-m-02 00:00:00')));
            $monthCut = $interval->m + ($interval->y * 12);
            if (strtotime($periodJson['gain_datetime']) < time() && $monthCut > 0) {
                $monthCut = -$monthCut;
            }
            if ($val < 1) {
                if ($now_nbr == 1) {
                    $params['coupon_detail_gain_datetime'] = date('Y-m-01 00:00:00', strtotime($periodJson['gain_datetime']));
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-t 23:59:59', strtotime($periodJson['gain_datetime']));
                } else {
                    $now_nbr -= 1;
                    $params['coupon_detail_gain_datetime'] = date('Y-m-01 00:00:00', strtotime("+" . ($now_nbr + $monthCut) . ' month'));
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-t 23:59:59', strtotime(date('Y-m-01 00:00:00') . "+" . ($now_nbr + $monthCut) . ' month'));
                }
            } else {
                if ($now_nbr == 1) {
                    $params['coupon_detail_gain_datetime'] = date('Y-m-01 00:00:00', strtotime($periodJson['gain_datetime']));
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-t 23:59:59', strtotime(date('Y-m-01 00:00:00') . "+" . ($val + $monthCut) . ' month'));
                } else {
                    $now_nbr -= 1;
                    $params['coupon_detail_gain_datetime'] = date('Y-m-01 00:00:00', strtotime("+" . ((($val + 1) * $now_nbr) + $monthCut) . ' month'));
                    $params['coupon_detail_deadline_datetime'] = date('Y-m-t 23:59:59', strtotime(date('Y-m-01 00:00:00') . "+" . ((($val + 1) * $now_nbr) + $val + $monthCut) . ' month'));
                }
            }
        }

        return $params;
    }
}