<?php
namespace EasyChat\Library\Commerce;

 
final class MoySkladCommerceContextProvider implements CommerceContextProviderInterface
{
    private $client;
    private $mapping;

    public function __construct(MoySkladClient $client, array $mapping = array()) { $this->client = $client; $this->mapping = $mapping; }

    public function capabilities(): array { return array('customer'=>true,'orders'=>true,'order_items'=>true,'read_only'=>true); }

    public function resolveCustomer(array $lookup): array
    {
        $found = array(); $evidence = array();
         
         
        foreach ($this->emails($lookup) as $email) $this->collect($found, $evidence, $this->client->counterparties('email', $email), 'email');
        foreach ($this->phones($lookup) as $phone) $this->collect($found, $evidence, $this->client->counterparties('phone', $phone), 'phone');
        if (!$found) return array('status'=>'not_found','reference'=>array());
        if (count($found) !== 1) return array('status'=>'ambiguous','reference'=>array());
        $row = reset($found); $id = (string)($row['id'] ?? '');
        $href = (string)($row['meta']['href'] ?? '');
        if ($id === '' || $href === '') return array('status'=>'unavailable','reference'=>array());
        return array('status'=>'matched','reference'=>array('id'=>$id,'kind'=>'counterparty_id','evidence'=>implode('+', array_keys($evidence[$id] ?? array())),'href'=>$href));
    }

    public function findOrders(array $reference, int $limit = 3): array
    {
        $rows = $this->client->customerOrders((string)($reference['href'] ?? ''), $limit);
        $orders = array();
        $order_hrefs = array(); foreach ($rows as $row) { $href = (string)($row['meta']['href'] ?? ''); if ($href !== '') $order_hrefs[] = $href; }
        $demands = $this->client->demands($order_hrefs, 4);
        $by_order = array(); foreach ($demands as $demand) { $href = (string)($demand['customerOrder']['meta']['href'] ?? ''); if ($href !== '') $by_order[$href][] = $demand; }
        foreach ($rows as $row) {
            $id = (string)($row['id'] ?? ''); if ($id === '') continue;
            $items = array();
            foreach (array_slice((array)($row['positions']['rows'] ?? array()), 0, 20) as $position) {
                $assortment = (array)($position['assortment'] ?? array());
                $items[] = array(
                    'name' => $this->plain($assortment['name'] ?? $position['name'] ?? 'Товар', 180),
                    'quantity' => max(1, (float)($position['quantity'] ?? 1)),
                    'product_id' => preg_replace('/[^A-Za-z0-9-]/', '', (string)($assortment['id'] ?? '')),
                    'stock' => isset($position['stock']['available']) && is_numeric($position['stock']['available'])
                        ? max(0, (float)$position['stock']['available'])
                        : null,
                );
            }
            $orders[] = array(
                'id'=>$id,
                'number'=>$this->plain($row['name'] ?? $id, 64),
                'date'=>$this->plain($row['moment'] ?? $row['created'] ?? '', 32),
                'updated_at'=>$this->plain($row['updated'] ?? $row['moment'] ?? $row['created'] ?? '', 32),
                'status'=>$this->plain($row['state']['name'] ?? 'Без статуса', 80),
                'total'=>$this->money($row['sum'] ?? 0),
                'payment'=>!empty($row['payedSum']) && (float)$row['payedSum'] >= (float)($row['sum'] ?? 0) ? 'Оплачен' : '',
                'delivery'=>'', 'payment_status'=>!empty($row['payedSum']) && (float)$row['payedSum'] >= (float)($row['sum'] ?? 0)?'paid':'pending',
                'refund_status'=>'unknown','fulfillment_status'=>$this->fulfillment((string)($row['state']['name']??'')),'shipments'=>$this->shipments($row, $by_order[$row['meta']['href'] ?? ''] ?? array()),'items'=>$items,
                'url'=>$this->safeUrl($row['meta']['uuidHref'] ?? ''),
                'source'=>'moysklad',
            );
        }
        return $orders;
    }

    public function getOrder(array $reference, string $order_id): array
    {
        foreach ($this->findOrders($reference, 10) as $order) if ((string)$order['id'] === $order_id) return $order;
        return array();
    }
    public function health(): array { try { return $this->client->test() + array('ready'=>true); } catch (\Throwable $e) { return array('ready'=>false,'reason'=>$e->getMessage()); } }
    public function explainIdentity(array $reference): array { return array('kind'=>'counterparty_id','evidence'=>(string)($reference['evidence'] ?? '')); }

    private function collect(array &$found, array &$evidence, array $rows, string $kind): void
    {
        foreach ($rows as $row) { $id=(string)($row['id']??''); if($id==='')continue; $found[$id]=$row; $evidence[$id][$kind]=true; }
    }
    private function emails(array $lookup): array { $r=array(); foreach((array)($lookup['emails']??array())as$v){$v=mb_strtolower(trim((string)$v),'UTF-8');if(filter_var($v,FILTER_VALIDATE_EMAIL))$r[$v]=$v;}return array_slice(array_values($r),0,1); }
    private function phones(array $lookup): array { $r=array();foreach((array)($lookup['phones']??array())as$v){$d=preg_replace('/\D+/','',(string)$v);if(strlen($d)===11&&$d[0]==='8')$d='7'.substr($d,1);if(strlen($d)>=10&&strlen($d)<=15){$r['+'.$d]='+'.$d;}}return array_slice(array_values($r),0,1); }
    private function plain($v,int $l): string { return mb_substr(trim(preg_replace('/\s+/u',' ',strip_tags((string)$v))),0,$l,'UTF-8'); }
    private function money($minor): string { return rtrim(rtrim(number_format(((float)$minor)/100,2,',',' '),'0'),',').' ₽'; }
    private function safeUrl($url): string { $url=(string)$url;return strpos($url,'https://online.moysklad.ru/')===0?$url:''; }
    private function shipments(array $order, array $demands): array
    {
        $out = array();
        foreach ($demands as $demand) {
            $attributes = array(); foreach ((array)($demand['attributes'] ?? array()) as $attribute) {
                $id = (string)($attribute['id'] ?? $attribute['meta']['href'] ?? '');
                if (preg_match('/^[0-9a-f-]{30,40}$/i', $id)) $id = strtolower($id);
                else $id = preg_match('~/attributes/([0-9a-f-]{30,40})$~i', $id, $m) ? strtolower($m[1]) : '';
                if ($id !== '') $attributes[$id] = is_array($attribute['value'] ?? null) ? (string)($attribute['value']['name'] ?? '') : (string)($attribute['value'] ?? '');
            }
            $carrier = (string)($demand['carrier']['name'] ?? '');
            if ($carrier === '') $carrier = $this->attribute($attributes, 'carrier');
            $tracking = $this->attribute($attributes, 'tracking_number');
            $client_number = $this->attribute($attributes, 'apiship_client_number');
            $external = $this->attribute($attributes, 'apiship_order_id');
            $provider = $this->attribute($attributes, 'provider_number');
            if ($tracking === '') $tracking = $provider !== '' ? $provider : $client_number;
            if ($carrier === '' && $tracking === '' && $external === '') continue;
            $out[] = array('carrier'=>$carrier,'carrier_code'=>$this->carrierCode($carrier),'tracking_number'=>$tracking,'external_order_id'=>$external,'client_number'=>$client_number,'provider_number'=>$provider,'source'=>'moysklad_demand','source_evidence'=>array('demand_id'=>(string)($demand['id'] ?? ''),'attributes'=>array_keys($attributes)),'updated_at'=>(string)($demand['updated'] ?? $demand['moment'] ?? ''));
        }
        return array_slice($out, 0, 4);
    }
    private function attribute(array $attributes, string $key): string { $id=(string)($this->mapping[$key]??''); return $id !== '' ? trim((string)($attributes[$id]??'')) : ''; }
    private function carrierCode(string $carrier): string { $v=mb_strtolower($carrier,'UTF-8'); if(strpos($v,'сдэк')!==false||strpos($v,'cdek')!==false)return'cdek';if(strpos($v,'почт')!==false)return'russian_post';if(strpos($v,'яндекс')!==false)return'yandex_delivery';if(strpos($v,'apiship')!==false)return'apiship';return''; }
    private function fulfillment(string $status): string{$status=mb_strtolower($status,'UTF-8');if(preg_match('/достав|выполн|заверш/u',$status))return'delivered';if(preg_match('/отправ/u',$status))return'shipped';if(preg_match('/готов/u',$status))return'ready';if(preg_match('/отмен|возврат/u',$status))return'cancelled';return'processing';}
}
