<?php

use lib\cache;

/**
 * 通用逻辑类
 */
class logicMod extends mod{
	public $db;
	protected $cacheSubject;
	protected $cacheSubjectByCrmKey;
	protected $cahceSubjectExt;
	protected $cahceTopSubject;
	function __construct(){
		$this->db = new db(\mvc::$cfg['libs']['database']['main']);
    }

	/**
	 * 取指定年月的最大期号
	 *
	 * @param int $yearMonth 202210 为2022年10月
	 * @return int
	 */
	public function getMaxCycleByYearMonth(int $yearMonth): int
	{
		$result = (new sqler($this->db))->table('voucher')->field('MAX(v_seq)')->where('v_cycle', $yearMonth)->one();
		return $result ?: 0;
	}

	/**
	 * 获取下一个期号
	 *
	 * @return int
	 */
	public function getNextCycle(): int
	{
		$result = $this->getMaxCycleByYearMonth(date('Y-m'));
		$result = $result + 1;
		return $result;
	}

	/**
	 * 获取凭证最大ID
	 *
	 * @return int
	 */
	public function getMaxId(): int
	{
		$result = (new sqler($this->db))->table('voucher')->max('v_id');
		return $result ?: 0;
	}

	/**
	 * 获取科目对象 by Crm 服务项目id
	 *
	 * @param string $parentId 科目父ID 例 主营业务收入 10094
	 * @return array
	 */
	public function getSubjectByCrmKey(int $parentId, $crmKey): array
	{
		$cacheKey = $parentId.'_'.$crmKey;
		if(!isset($this->cacheSubjectByCrmKey[$cacheKey])){
			$q = new sqler($this->db);
			$row = $q->table('object')
				->where('o_parent_id', $parentId . '.')
				->and('o_crm_key', $crmKey)
				->row();
			$this->cacheSubjectByCrmKey[$cacheKey] = $row;
		}
		return $this->cacheSubjectByCrmKey[$cacheKey];
	}

	/**
	 * 获取科目信息
	 *
	 * @param int:array $id 科目ID 或者传入 科目的 row 记录
	 * @return array
	 */
	public function getSubject($id): array
	{
		if (is_array($id)) {
			return  $id;
		} else {
			$cacheKey = $id;
			if (!isset($this->cacheSubject[$cacheKey])) {
				$row = (new sqler($this->db))->table('object')->where('o_id', $id)->row();
				$this->cacheSubject[$cacheKey] = $row;
			}
			return $this->cacheSubject[$cacheKey];
		}
	}


	/**
	 * 获取最顶级节点信息
	 *
	 * @param int:array $id 科目ID 或者传入 科目的 row 记录
	 * @return array
	 */
	public function getTopSubject($id): array
	{
		$cacheKey = md5(serialize($id));
		if (isset($this->cahceTopSubject[$cacheKey])) {
			return $this->cahceTopSubject[$cacheKey];
		}
		$row = $this->getSubject($id);
		if ($row) {
			$result = (new sqler($this->db))->table('object')
				->where('o_level', 0)
				->and('o_lft{<}', $row['o_lft'])
				->and('o_rgt{>}', $row['o_rgt'])
				->row();
		} else {
			$result = [];
		}
		$this->cahceTopSubject[$cacheKey] = $result; 
		return $result;
	}

	/**
	 * 获取科目扩展信息
	 *
	 * @param int:array $id 科目ID 或者传入 科目的 row 记录
	 * @return array
	 * @example 返回结果样例
	 *  - [
	 *  - - "id" => "2" (1),
	 *  - - "name" => "余额方向" (12),
     *  - - "type" => "int" (3),
     *  - - "in_object" => "id" (2),
     *  - - "value" => "204" (3),
     *  - - "text" => "贷" (3)
     *  - ]
	 */
	public function getSubjectExt($id): array
	{
		$cacheKey = md5(serialize($id));
		if(isset($this->cahceSubjectExt[$cacheKey])){
			return $this->cahceSubjectExt[$cacheKey];
		}
		$row = $this->getSubject($id);
		$topRow = $this->getTopSubject($row);
		$q = new sqler($this->db);
		$extRows = $q->table('object_ext')
			->where('oe_o_id', $topRow['o_id'])
			->map('oe_id')
			->all();
		$keys = array_keys($extRows);
        if(empty($keys)){
            throw new \Exception(json_encode($id)." 构建失败,缺失基础数据表或是记录");
        }

		$valRows = $q->table('object_ext_val')
			->where('oev_o_id', $row['o_id'])
			->and('oev_oe_id', $keys)
			->map('oev_oe_id')
			->all();
		$result = [];
		foreach ($extRows as $oe_id=>$row){
			$value = $valRows[$row['oe_id']]['oev_' . $row['oe_type']];
			$text = $value;
			$sets = [];
			if ($row['oe_in_object'] == 'id') {
				$t = $this->getSubject($value);
				$text = $t ? $t['o_name'] : $text;
			}else if ($row['oe_in_object'] == 'sets' && $value) {
				$sets = json_decode($value,true);
				if($sets){
					$t = $q->table('object')->where('o_id', $sets)->all();
					$text = '';
					foreach ($t as $k=>$v){
						if($text!='') $text.=', ';
						$text .= $v['o_name'];
					}
				}
			}
			$result[$oe_id] = [
				'id' => $row['oe_id'], 
				'name' => $row['oe_name'],
				'type' => $row['oe_type'],
				'in_object' => $row['oe_in_object'],
				'value' => $value,
				'sets' => $sets,
				'text' => $text,
			];
		}
		$this->cahceSubjectExt[$cacheKey] = $result;
		return $result;
	}


	/**
	 * 构建一条凭证记录
	 *
	 * @param int:array $id 科目ID 或者传入 科目的 row 记录
	 * @return array
	 */
	public function buildVoucherRow(array $data): array
	{
		$date = $data['date'];
		if(!is_numeric($date)){
			$date = strtotime($date);
		}
		$vid =  $data['vid'] ?: null;
		$v_seq =  $data['seq'] ?: null;
		$v_cycle = date('Ym', $date);
		//科目
		$subjectPrentId = $data['subjectPrentId'] ?: 0; //科目父ID 例 主营业务收入 10094
		$subjectCrmKey = $data['subjectCrmKey'] ?: '';
		$subjectRow = $data['subjectRow'] ?: null; //object 科目记录 如果指定了，则 subjectPrentId 和 subjectCrmKey 参数忽略 
		//部门
		$depCrmKey = $data['depCrmKey'] ?: null;
		$depRow = $data['depRow'] ?: null; //object行记录 如果指定了，则 depCrmKey 参数忽略 
		//职员
		$userCrmKey = $data['userCrmKey'] ?: null;
		$userRow = $data['userRow'] ?: null; //object行记录 如果指定了，则 userCrmKey 参数忽略 

		$money = $data['money'] ?: null;
		$v_client = $data['client'];
		$v_summary = mb_substr($data['summary'], 0, 800);
		$v_state = $data['state'] ?: 0;  //0:草稿,1:已审核，2:废弃,3:删除
		
		$now = date('Y-m-d H:i:s');
		if(!$subjectRow){
			$subjectRow = $this->getSubjectByCrmKey($subjectPrentId, $subjectCrmKey);
			if(empty($subjectRow)){
				throw new \Exception("构建失败,缺失科目[主科目ID, CrmKey] [". $subjectPrentId .',' .$subjectCrmKey.']'
										.json_encode($data, JSON_UNESCAPED_UNICODE));
			}
		}

		if(is_null($v_seq) || is_null($subjectRow) || is_null($money)){
			return [];
			//throw new \Exception("构建失败,缺失元素或元素值".json_encode($data));
		}

		//取对应科目信息
		$extRows = $this->getSubjectExt($subjectRow);
		$v_subject = $subjectRow['o_id'] ?: '';

		//借贷金额与方向
		$v_j = 0;
		$v_d = 0;
		if ((isset($data['direction']) && $data['direction']==0) || (!isset($data['direction']) && $extRows[2]['text'] == '贷')) {
				$v_d = $money;
			$v_direction = 0;
		} else {
			$v_j = $money;
			$v_direction = 1;
		}

		//核算对象
		$v_object_1 = null;
		$v_object_2 = null;
		 //部门
		//if (in_array('1', $extRows[3]['sets'])) {
			if (!$depRow) {
				$depRow = $this->getSubjectByCrmKey(1, $depCrmKey);
			}
			if($depRow) $v_object_1 = $depRow['o_id'];
		//}
		//职员
		//if (in_array('2', $extRows[3]['sets'])) { 
			if (!$userRow) {
				$userRow = $this->getSubjectByCrmKey(2, $userCrmKey);
			}
			if ($userRow) $v_object_2 = $userRow['o_id'];
		//}
		return [
			'v_id' => $vid,
			'v_cycle' => $v_cycle,
			'v_seq' => $v_seq,
			'v_year' => date('Y', $date),
			'v_date' => date('Y-m-d', $date),
			'v_subject' => $v_subject,
			'v_j' => $v_j,
			'v_d' => $v_d,
			'v_direction' => $v_direction,
			'v_object_1' => $v_object_1,
			'v_object_2' => $v_object_2,
			'v_object_4' => null, //弃用
			'v_client' => $v_client,
			'v_summary' => $v_summary,
			'v_state' => $v_state,
			'create_time' => $now,
			'update_time' => $now,
		];
	}

}

