<?php defined('BASEPATH') OR exit('No direct script access allowed');

class GuestOrder extends Base_table {

	public $cId = null;

	public $bId = null;

	private $comp = null;

	private $settings = null;

	private $hasBranch = false;

	private $ci = null;

	function __construct($conf=array())
	{
		parent::__construct(array(
			'tbl' => 'trans',
			'tbl_key' => 'id'
		));

		if ($conf && $conf["cId"])
		{
			$this->cId = $conf["cId"];
			$this->loadSettings();
		}

		$this->ci =& get_instance();
		$this->ci->load->library('trans_table');
		$this->ci->trans_table->cId = $this->cId;
	}

	private function loadSettings($cId=null)
	{
		if (!empty($cId))
		{
			$this->cId = $cId;
		}

		$this->db->select("salModCodes, resetSeries")->from("compsettings")->where("cId", $this->cId);
		$this->settings = $this->db->get()->row_array();

		$this->db->select("code, value")->from("compconfig")->where("cId", $this->cId);
		$compconfig = $this->db->get()->result_array();
		if (!empty($compconfig))
		{
			foreach($compconfig as $conf)
			{
				$this->settings[$conf["code"]] = $conf["value"];
			}
		}

		if (empty($this->settings["gstin"]))
		{
			$this->settings["gstin"] = "";
		}

		if (empty($this->settings["isCompositionScheme"]))
		{
			$this->settings["isCompositionScheme"] = false;
		}

		if(!empty($this->settings["salModCodes"]))
		{
			$salModCodes = explode(",", $this->settings["salModCodes"]);
			$this->hasBranch = in_array("BL", $salModCodes) ? true : false;
		}

        return $this->settings;
	}

	public function save($postData, $params = array())
	{
		if (empty($postData) || empty($postData["items"]))
		{
			$this->error = "";
			return false;
		}

		$this->check_address($postData);

		$compStateCode = $this->comp["stateCode"];

		$postData["stateType"]	= ($compStateCode == $postData["address"]["stateCode"]) ? "I" : "X";
		$postData["includeTax"]	= 1;
		$postData["taxableAmount"] = 0;
		$postData["totAmount"] = 0;
		$postData["totTax"] = 0;
		$postData["roundAmount"] = 0;
		$postData["source"] = empty($postData["source"]) ? "L" : $postData["source"];

		$this->db->trans_start();
		$this->save_trans($postData);

		$this->save_trans_addr($postData);

		$this->save_trans_items($postData);

		$this->db->update("trans", array(
			"taxableAmount" => $postData["taxableAmount"],
			"totAmount"		=> $postData["totAmount"],
			"totTax"		=> $postData["totTax"],
			"roundAmount"	=> $postData["roundAmount"]
		), array(
			"cId"	=> $this->cId,
			"id"	=> $postData["transId"]
		));

		$this->db->trans_complete();

		return $postData;
	}

	public function save_trans(&$postData)
	{
		$this->ci->trans_table->bId = $this->bId = $postData["bId"];

		$postData["tDate"] = !empty($postData["tDate"]) ? $postData["tDate"] : date("Y-m-d");
		$postData["tType"] = !empty($postData["tType"]) ? $postData["tType"] : "SO";

		if (empty($postData["tNo"]) || empty($postData["id"]))
		{
			$seriesData = array(
				"tType" => $postData["tType"],
				"tDate" => $postData["tDate"],
				"tNo"	=> "", // $postData["tNo"]
			);
			$this->ci->trans_table->create_tNo($seriesData);

			$postData["tNo"] = $seriesData["tNo"];
			$postData["seriesId"] = $seriesData["seriesId"];
			$postData["id"] = $seriesData["id"];
		}

		$trans = array(
			"id"	=> $postData["id"],
			"cId"	=> $this->cId,
			"tType"	=> $postData["tType"],
			"tNo"	=> $postData["tNo"],
			"seriesNo" => $postData["tNo"],
			"tDate" => $postData["tDate"],
			"ref" => "",
			"ref_id" => "",
			"notes" => "",
			"status" => "D",

			"conId"			=> !empty($postData["conId"]) ? $postData["conId"] : "",
			"conName"		=> !empty($postData["conName"]) ? $postData["conName"] : $postData["address"]["name"],
			"conStateCode"	=> !empty($postData["conStateCode"]) ? $postData["conStateCode"] : $postData["address"]["stateCode"],
			"conStateId"	=> !empty($postData["conStateId"]) ? $postData["conStateId"] : $postData["address"]["stateId"],
			"conLocCode"	=> $postData["stateType"],
			"conTaxNo"		=> !empty($postData["conTaxNo"]) ? $postData["conTaxNo"] : "",
			"conTaxScheme"	=> !empty($postData["conTaxScheme"]) ? $postData["conTaxScheme"] : "U", // C-Composition Scheme, U-Unregister, R-Registered
			"dueDate"		=> "",

			"taxableAmount" => 0,
			"roundAmount" => 0,
			"totTax" => 0,
			"totAmount" => 0,
			"includeTax" => $postData["includeTax"],
			"source" => $postData["source"],
			"bId" => $this->bId
		);

		// Insert in trans
		$this->db->update("trans", $trans, array(
			"id" => $postData["id"]
		));
		$postData["transId"] = $postData["id"];

		return $postData["transId"];
	}

	public function save_trans_items(&$postData)
	{
		$itemIds = array_column($postData["items"], "itemId");
		$postData["items"] = array_combine($itemIds, $postData["items"]);

		$items = $this->getSelectedItems($itemIds);

		$hasTax = true;

		if (empty($this->settings["gstin"]) || $this->settings["isCompositionScheme"])
		{
			$hasTax = false;
		}

		if ($hasTax)
		{
			$taxIds = array_column($items, "taxId");
			$taxes = $this->getTaxes(array_unique($taxIds), $postData["stateType"]);

			$transTax = array();
			$taxRates = array();

			foreach ($taxes as $tax)
			{
				if (empty($taxRates[$tax["taxId"]]))
				{
					$taxRates[$tax["taxId"]] = 0;
				}

				$taxRates[$tax["taxId"]] += (float)$tax["taxRate"];
			}
		}

		foreach($items as $key => &$item)
		{
			$item["qty"] = $postData["items"][$item["itemId"]]["qty"];
			$item["taxableAmount"] = $item["itemTotal"] = $item["qty"] * $item["rate"];
			$item["taxAmount"] = 0;

			if ($hasTax)
			{
				if (!empty($item["taxId"]) && $postData["includeTax"])
				{
					$item["taxableAmount"] = round($item["itemTotal"] / (1 + $taxRates[$item["taxId"]] / 100), 2);
					$item["taxAmount"] = $item["itemTotal"] - $item["taxableAmount"];
				}
				else
				{
					$item["taxAmount"] = round($item["taxableAmount"] * $taxRates[$item["taxId"]] / 100, 2);
					$item["itemTotal"] = $item["taxableAmount"] + $item["taxAmount"];
				}
			}

			$postData["taxableAmount"] += $item["taxableAmount"];
			$postData["totAmount"] += $item["itemTotal"];
			$postData["totTax"] += $item["taxAmount"];

			$item["transId"] = $postData["transId"];
			$item["cId"] = $this->cId;
			$item["transId"] = $postData["transId"];

			$this->db->insert("trans_items", $this->strip_fields($item, array(
				"id", "transId", "cId", "itemId", "itemName", "itemDesc", "itemType", "itemHS", "rate",
				"qty", "freeQty", "discPercentage", "discAmount", "unit", "taxableAmount", "taxId", "taxName",
				"itemTotal", "accId", "itc", "itemAttrId", "mrp", "locId", "refTitemId", "chargesAmount"
			)));
			$item["transItemId"] = $this->db->insert_id();

			if ($hasTax)
			{
				// Prepare ob_trans_tax
				foreach($taxes as $tax)
				{
					$key = $postData["transId"] . "-" . $this->cId . "-" . $item["transItemId"] . "-" . $tax["taxTypeCode"] . "-" . $tax["taxCalc"];
					if (empty($transTax[$key]))
					{
						$transTax[$key] = array(
							"transId"	=> $postData["transId"],
							"cId"		=> $this->cId,
							"transItemID"	=> $item["transItemId"],
							"taxTypeCode"	=> $tax["taxTypeCode"],
							"taxRate"	=> $tax["taxRate"],
							"taxValue"	=> round($item["taxableAmount"] * $tax["taxRate"] / 100, 2),
							"itc"		=> $item["itc"],
							"taxCalc"	=> $tax["taxCalc"]
						);
					}
					else
					{
						$transTax[$key]["taxRate"] += $tax["taxRate"];
					}
				}
			}
		}

		if ($hasTax && !empty($transTax))
		{
			$this->db->insert_batch("trans_tax", array_values($transTax));
		}
	}

	public function save_trans_addr(&$postData)
	{
		$postData["address"]["addrType"] = "A";

		$trans_addr = $this->strip_fields(array_merge(array(
			"transId" => $postData["transId"],
			"cId" => $this->cId,
		), $postData["address"]), array(
			"transId", "cId", "name", "addrType", "address1", "address2",
			"city", "stateCode", "stateId", "stateName", "zip", "countryCode",
			"country", "phone", "extraCont"
		));

		// Insert in trans_addr
		$this->db->insert("trans_addr", $trans_addr);
	}

	public function getSelectedItems($itemIds = array())
	{
		$this->db->select("itemId, cId, name AS itemName, saleDesc AS itemDesc, type AS itemType, HS AS itemHS, saleRate AS rate, 1 AS qty, 0 AS discPercentage, 0 AS discAmount, uom AS unit, taxId, saleAccount AS accId, itc");
		$this->db->from("items");
		$this->db->where("cId", $this->cId);
		$this->db->where_in("itemId", $itemIds);
		$result = $this->db->get()->result_array();

		return $result;
	}

	public function getTaxes($taxIds, $stateType)
	{
		$this->db->select("t.id AS taxId, t.name AS taxName, t.taxCode, td.id AS taxDetailId, td.taxTypeCode, td.taxRate, td.stateType, td.taxCalc");
		$this->db->from("tax AS t");
		$this->db->join("taxdetail AS td", "td.taxId=t.id");
		$this->db->where("t.cId", $this->cId);
		$this->db->where("td.stateType", $stateType);
		$this->db->where_in("t.id", $taxIds);

		$result = $this->db->get()->result_array();

		return $result;
	}

	private function companyDetails()
	{
		// city, zip,
		
		$this->comp = $this->db->select("stateCode, stateId, stateName, countryCode, country")->from("companies")->where(array(
			"id" => $this->cId
		))->get()->row_array();

		return $this->comp;
	}

	private function check_address(&$data)
	{
		if (!empty($data["conId"]))
		{
			$contact = $this->db->select("id AS conId, name AS conName, stateCode AS conStateCode, stateId AS conStateId, name, company, stateCode, stateId, email, contactPerson, contactPersonMobile, taxNo, conTaxScheme")->from("contacts")->where(array(
				"cId" => $this->cId,
				"id" => $data["conId"]
			))->get()->row_array();

			$data = array_merge($data, $contact);

			$address = $this->db->select("*")->from("contacts_address")->where(array(
				"cId" => $this->cId,
				"conId" => $data["conId"]
			));
			$this->db->where("addrType", "A")->or_where("addrType", "B")->limit(1);
			$address = $this->db->get()->row_array();
			if (empty($address["name"])) {
				$address["name"] = $data["conName"];
			}
			if (empty($address["email"])) {
				$address["email"] = $data["email"];
			}
			$data["address"] = $address;
		}

		$company = $this->companyDetails();

		if (empty($data["stateId"]))
		{
			$data["stateId"] = $company["stateId"];
		}

		if (empty($data["stateCode"]))
		{
			$data["stateCode"] = $company["stateCode"];
		}

		if (empty($data["stateName"]))
		{
			$data["stateName"] = $company["stateName"];
		}

		if (empty($data["countryCode"]))
		{
			$data["countryCode"] = $company["countryCode"];
		}

		if (empty($data["country"]))
		{
			$data["country"] = $company["country"];
		}
	}

	public function get_series($data= array())
	{
		$result = array();
		$tDate	= !empty($data['tDate']) ? $data['tDate'] : date('Y-m-d');
		$bId 	= !empty($this->bId) ? $this->bId : get_company('mainbId');

		$unique_branch	= 0;
		$start_date = $end_date = $tDate;
		get_financial_dates($tDate, $start_date, $end_date);
		$fYear = date('Y', strtotime($start_date));

		$where = array('cId' => $this->cId);
		
		if (!empty($this->settings["resetSeries"]))
		{
			$this->db->select("id,tType,prefix,suffix,editable,manual,if(seriesStart and seriesStart>length(nxtNumber),LPAD(nxtNumber,seriesStart,'0'),nxtNumber) as nxtNumber,fYear,sName, classCode",false);
            $this->db->select('bId',false);
			$this->db->from("series");
			$where['fYear'] = $fYear;
			$where['bId'] = $bId;// get_company('mainbId');
			if ($this->hasBranch)
			{
				unset($where['bId']);
				$this->db->group_start();
				$this->db->where('bId', $bId);
				// if (empty($data['unique_branch'])) { 
					$this->db->select('followbId,find_in_set('.$bId.',followbId) as is_follow',false);
					$this->db->or_where('find_in_set('.$bId.',followbId) > 0',null,false);
				// }
				$this->db->group_end();
			}
			$this->db->where($where);
			$query = $this->db->get();
			$result = $query->result_array();

			if ($result && !empty($result[0]['is_follow']) && !empty($data['unique_branch']))
			{
                return array();
			}
		}

        return $result;
	}

    function cal_nxt_number($tno='1', $series= array())
	{
		if ($series && !empty($series['manual']))
		{
			if (!empty($series['prefix']))
			{
				$tno = preg_replace('#^'.preg_quote($series['prefix']).'#', '',$tno);
			}

			if (!empty($series['suffix']))
			{
				$tno = preg_replace('#'.preg_quote($series['suffix']).'$#', '',$tno);			
			}

			$next_num = "";
			if (is_string($tno))
			{
				preg_match('/(\d+)$/', $tno, $matches);
				if (count($matches) == 2)
				{
					$next_num = $matches[0];
					$next_num = str_replace($next_num, str_pad($next_num+1, strlen($next_num), 0, STR_PAD_LEFT), $tno);
				}
			}
			else if (is_number($tno))
			{
				$next_num = str_pad($tno+1, strlen($tno), 0, STR_PAD_LEFT);
			}
		}
		else
		{
			$next_num = !empty($series['nxtNumber'])?(int)$series['nxtNumber']:(int)$tno;
			$next_num++;
		}

		return $next_num;
	}

    public function get_tno()
    {
		/*
		$this->ci->load->library('trans_table');
		$this->ci->trans_table->cId = $this->cId;
		$this->ci->trans_table->bId = $this->bId;
		*/
		$tDate = gmdate('Y-m-d');
		$typeCode = 'SO';
		$tmp = array(
        	"tDate" => gmdate('Y-m-d'),
        	"bId" => !empty($this->bId) ? $this->bId : get_company('mainbId'),
        	"resetSeries" => $this->settings["resetSeries"],
        	"modules" => array(
				"SO" => array(
				    "value" => "Sales Order",
				    "prefix" => "ORD",
				    "series" => 1,
				    "typeCode" => "salord"
				)
			)
        );

		$result = $this->ci->trans_table->get_tno($typeCode, $tmp);

		return $result;
    }
}
