<?php

namespace App\Utils\CreditCard;

/**
 * Utilities strictly related to CC nunbers.
 * @author Gabriel Grosu
 */
class NumberDetails
{
	/**
	 * The list of credit card companies (providers)
	 * @var array
	 */
	private const COMPANIES_CODES = [
		'amex'					=> 'AX',
		'unionpay'				=> 'UP',
		'diners_club'			=> 'DC',
		'discover'				=> 'DS',
		'jcb'					=> 'JC',
		'maestro'				=> 'maestro',
		'mastercard'			=> 'CA',
		'visa_electron'			=> 'VI',
		'visa'					=> 'VI',
		'forbrugsforeningen'	=> 'forbrugs',
		'dankort'				=> 'dankort',
		'elo'					=> 'EL',
		'hipercard'				=> 'hipercard',
	];

	/**
	 * The original CC number.
	 * @var string
	 */
	private string $originalNumber;

	/**
	 * The cleaned CC number (contains only digits).
	 * @var string
	 */
	private string $cleanNumber;

	/**
	 * Populates the original CC numnber.
	 * @param string $originaNumber
	 */
	public function __construct(string $originaNumber='')
	{
		$this->originalNumber = $originaNumber;
		$this->cleanNumber = $this->cleanNumber($originaNumber);
	}

	/**
	 * Returns the clean CC number (keeps only digits).
	 * @return mixed
	 */
	private function cleanNumber($originalNumber)
	{
		return preg_replace('/[^0-9]/', '', $originalNumber);
	}

	/**
	 * Statically creates a new object.
	 * @param string $originalNumber
	 * @return \App\Utils\CreditCard\NumberDetails
	 */
	static public function create(string $originalNumber='') :self
	{
		return new self($originalNumber);
	}

	/**
	 * Cleans the CC number but only possible separators (space, dot, dash, slash, etc). The
	 * number will still contain letters or other chars.
	 * @return string
	 */
	public function getStrippedNumber() :string
	{
		return str_replace([' ', '-', '.', '/'], '', $this->originalNumber);
	}


	/**
	 * Returns the credit card number by obfuscating the digits (only the first 6 digits and the last 4 digits are kept).
	 * This will start from the stripped number, not the clean or the original one.
	 * @param string $maskingPlaceholder
	 * @return string
	 */
	public function getMaskedNumber($maskingPlaceholder='X') :string
	{
		$initalCcNumber = $this->getStrippedNumber();
		// if length is 4 chars or less, just return that
		if (strlen($initalCcNumber)<=10) {
			return $initalCcNumber;
		}

		return substr($initalCcNumber, 0, 6)
			. str_repeat($maskingPlaceholder, strlen($initalCcNumber) -6 -4)
			. substr($initalCcNumber, -4);
	}

	/**
	 * Indicates if the current CC number is valid.
	 * @return boolean
	 */
	public function isValid()
	{
		return $this->getDetails()['valid'];
	}


	/**
	 * Return array of details related to CC number (valid, company).
	 */
	public function getDetails() :array
	{

		$cardDetails = \Freelancehunt\Validators\CreditCard::validCreditCard($this->cleanNumber);

		return [
			'valid' => $cardDetails['valid'],
			'companyName' => $cardDetails['type'],
			'companyCode' => self::COMPANIES_CODES[$cardDetails['type']]??null,
		];

	}

}



/*

Sabre CC vendor codes:

CODE	VENDOR NAME
AA	AMERICAN AIR CR CARD
AB	AUSTRALIAN BANKCARD
AH	ACCOR HOSPITALITY BUSINESS ACCOUNT
AQ	ALOHA AIR CR CARD
AS	ALASKA AIR CR CARD
AX	AMERICAN EXPRESS
BA	VISA
BB	BARCLAYS BANK/VISA
BC	BANKCARD
BE	BE IHG BUSINESS ACCOUNT
BF	C B B FRANCAIS/VISA
BH	BANK OF HAWAII
BI	BRANIFF FASTCHARGE
BJ	BANK CARD JAPAN
BP	BANK CARD PACIFIC
BZ	NEW ZEALAND BANKCARD
CA	MASTERCARD
CB	CARTE BLANCHE
CG	CHARGEX/VISA
CN	KB CARD
CO	CONTINENTAL TVL CARD
CP	CANADIAN AIR CR CARD
CS	CARTA SI
CT	CTC MX
CU	CONN B AND T CO
CX	CHOICE
DC	DINERS CLUB
DI	MGM GRAND AIR CARD
DL	DELTA AIR CREDIT CARD
DP	A R C DIRECT FOP
DS	DISCOVER CARD
DT	CHINA AIR DYNASTY CD
DW	DISNEY CREDIT CARD
EB	KOREAN EXCHANGE BANK
EC	EUROCARD
EL	CARTAO ELO
ER	ENROUTE
EW	EASTERN WINGS CARD
FC	EASTERN FAST CARD
FH	FED NATL HOTELIERE
GR	GOVERNMENT
GW	GREAT WALL
HA	HAWAIIAN AIR CR CARD
HD	HYUNDAI CARD
HS	HSBC
ID	COMITES
IK	MASTERCARD
IL	ENROUTE
JB	JCB INTERNATIONAL
JC	JCB INTERNATIONAL
KA	WOORI BANK APS
KC	KOKUNAI SHINPAN
LC	LOTTE CARD
LG	LG CARD
LH	LUFTHANSA CRTSY CARD
LO	LOTTE
L1	LUFTHANSA
L2	LUFTHANSA
MC	MILLION CREDIT SERVICE
MD	DIAMOND CREDIT
MR	MIR CARD
MT	EMPIRE CARD
NC	NIHON SHINPAN
NH	NONGHYUP CARD
NW	NORTHWEST AIR CR CD
NZ	AIR NEW ZEALAND TRAVELCARD
OT	OTB CARD
PI	PIEDMONT CR CARD
PS	PSA CREDIT CARD
RA	RAPTIME-FRANCE
RJ	ROYAL JORDANIAN CR CARD
SC	SHOPPERS CHARGE
SH	SHINHAN CARD
SI	JET AMERICA TVL CARD
SK	HANA SK
SO	SOLLO
SR	SELECT CARD
SW	SAMSUNG CARD
TC	TRUST CARD
TN	TARJETA NARANJA
TP	AIR TRAVEL CARD
TW	TWA CREDIT CARD
UA	UNITED CREDIT CARD
UC	UNITED TRAVEL CARD
UD	UNION CREDIT
UI	UNITED DEBIT CRD CTR
UP	UNIONPAY
VI	VISA
VN	VN LOCAL CARD PAYMENT CODE
WB	WALKER BANKARD
WC	MOTEL 6 WELCOME CARD
XS	ACCESS CARD
ZA	ACCESSAIR CR CARD
ZE	HERTZ
ZP	AIR ST THOMAS
ZR	DOLLAR CREDIT CARD
*/
