#include "sl0200.h"

#include "../ve/velib04.h"
#include "../ca/commesse.h"

///////////////////////////////////////////////////////////
// TCertificazione
///////////////////////////////////////////////////////////

class TCertificazione : public TElaborazione_esterna
{
protected:
  const TRectype& find_cert(const TDocumento& doc);
  void set_codiva(TRiga_documento& rdoc) const;

public:
  virtual bool elabora(TLista_documenti& doc_in, TLista_documenti& doc_out,
                       const TDate& data_elab, bool interattivo = false);
  TCertificazione(const TString& cod);
};

const TRectype& TCertificazione::find_cert(const TDocumento& doc)
{
  const TString& codnum = codice_numerazione_finale();
  TString query, limit;
  limit << RDOC_DAPROVV  << '=' << doc.get(DOC_PROVV)    << ' ' 
        << RDOC_DAANNO   << '=' << doc.get_int(DOC_ANNO) << ' '  
        << RDOC_DACODNUM << '=' << doc.get(DOC_CODNUM)   << ' '  
        << RDOC_DANDOC   << '=' << doc.get_long(DOC_NDOC);
  query << "USE 34 KEY 4"
        << "\nSELECT CODNUM=\"" << codnum << '"'
        << "\nFROM " << limit << "\nTO " << limit;
  
  TISAM_recordset recset(query);
  const TRectype& rdoc = recset.cursor()->curr();
  TToken_string key;
  if (recset.move_first())
  {
    key = rdoc.get(RDOC_PROVV);
    key.add(rdoc.get(RDOC_ANNO));
    key.add(rdoc.get(RDOC_CODNUM));
    key.add(rdoc.get(RDOC_NDOC));
  }
  
  return cache().get(LF_DOC, key);
}

void TCertificazione::set_codiva(TRiga_documento& rdoc) const
{
  TString4 codiva;

  const TString80 codcms = rdoc.doc().get(DOC_CODCMS);
  if (codcms.full())
  {
    const TRectype& cms = cache().get(LF_COMMESSE, codcms);
    if (!cms.empty())
    {
      rdoc.put(RDOC_CODCMS, codcms);
      codiva = cms.get(COMMESSE_CODIVA);
    }
  }

  const TString80 codart = rdoc.get(RDOC_CODART);
  if (codart.full())
  {
    const TRectype& ana = cache().get(LF_ANAMAG, codart);
    if (!ana.empty())
    {
      rdoc.put(RDOC_CODARTMAG, codart);
      rdoc.put(RDOC_CHECKED, true);

      TToken_string key; key.add(codart); key.add(1);
      const TString& um = cache().get(LF_UMART, key, UMART_UM);
      rdoc.put(RDOC_UMQTA, um);

      if (codiva.blank())
        codiva = ana.get(ANAMAG_CODIVA);
    }
  }

  rdoc.put(RDOC_CODIVA, codiva);
  rdoc.importo(true, false); // Ricalcola IMPNS
}

bool TCertificazione::elabora(TLista_documenti& doc_in, TLista_documenti& doc_out,
                           const TDate& data_elab, bool interattivo)
{
  for (int i = 0; i < doc_in.items(); i++)
  {
    TDocumento& din = doc_in[i];

    // Mi assicuro che ad ogni documento in ingresso ne corrisponda uno in uscita
    if (i >= doc_out.items()) 
    {
      const TRectype& cert = find_cert(din);
      if (!cert.empty())
      {
        if (interattivo)
          warning_box("Il documento S.A.L. aggiorner� il certificato %s %d/%ld", 
                      (const char*)cert.get(DOC_CODNUM), cert.get_int(DOC_ANNO), cert.get_long(DOC_NDOC));
      }

      TDocumento* doc = NULL;
      if (cert.empty())
      {
        doc = new TDocumento('D', data_elab.year(), codice_numerazione_finale(), 0L);
        doc->put(DOC_TIPODOC, tipo_finale());
      }
      else
      {
        doc = new TDocumento(cert);
        doc->destroy_rows();
      }
      doc_out.add(doc);
    }

    TDocumento& don = doc_out[i];

    din.put(DOC_STATO,      stato_finale_doc_iniziale());
    
    don.put(DOC_NUMANT,     din.get(DOC_NUMANT));
    don.put(DOC_TIPOCF,     din.get(DOC_TIPOCF));
    don.put(DOC_CODCF,      din.get(DOC_CODCF));
    don.put(DOC_DATADOC,    data_elab);
    don.put(DOC_NOTE,       din.get(DOC_NOTE));
    don.put(DOC_CODCMS,     din.get(DOC_CODCMS));
    don.put(DOC_STATO,      stato_finale());
    don.put(DOC_NUMDOCRIF,  din.get(DOC_NDOC));
    don.put(DOC_DATADOCRIF, din.get(DOC_DATADOC));

    // don.put(DOC_G1,         din.get(DOC_G1));
    TToken_string g1(din.get(DOC_G1), '\n');
    FOR_EACH_TOKEN(g1, tok)
    {
      TToken_string fld(tok, '=');
      const char* name = fld.get(0);
      const char* value = fld.get();
      don.put(name, value);
    }

    const bool is_cli = don.get_char(DOC_TIPOCF) != 'F';
    const real sal_sal = din.get("SAL_SAL");
    if (sal_sal > ZERO)
    {
      TRiga_documento& rdoc = don.new_row("01");
      rdoc.put(RDOC_CODART, ini_get_string(CONFIG_DITTA, "ci", is_cli ? "CODARTLC" : "CODARTLF"));
      rdoc.put(RDOC_QTA, UNO);
      rdoc.put(RDOC_DESCR, TR("Lavori eseguiti"));
      rdoc.put(RDOC_PREZZO, sal_sal);
      rdoc.set_original_rdoc_key(din[1]);
      set_codiva(rdoc);
    }

    const real sal_gar = din.get("SAL_GAR");
    if (sal_gar > ZERO)
    {
      TRiga_documento& rdoc = don.new_row("01");
      rdoc.put(RDOC_CODART, ini_get_string(CONFIG_DITTA, "ci", is_cli ? "CODARTGC" : "CODARTGF"));
      rdoc.put(RDOC_QTA, -UNO);
      rdoc.put(RDOC_DESCR, TR("Ritenuta a garanzia"));
      rdoc.put(RDOC_PREZZO, sal_gar);
      rdoc.set_original_rdoc_key(din[1]);
      set_codiva(rdoc);
    }

    const real sal_ant = din.get("SAL_ANT");
    if (sal_ant > ZERO)
    {
      TRiga_documento& rdoc = don.new_row("01");
      rdoc.put(RDOC_CODART, ini_get_string(CONFIG_DITTA, "ci", is_cli ? "CODARTAC" : "CODARTAF"));
      rdoc.put(RDOC_QTA, -UNO);
      rdoc.put(RDOC_DESCR, TR("Anticipi"));
      rdoc.put(RDOC_PREZZO, sal_ant);
      rdoc.set_original_rdoc_key(din[1]);
      set_codiva(rdoc);
    }

    din.rewrite(); // Aggiorna codici fase nelle righe
    don.write();   // Salva ordine
  }
  
  return true;
}

TCertificazione::TCertificazione(const TString& cod) : TElaborazione_esterna(cod) 
{ 
}

///////////////////////////////////////////////////////////
// Utility pubbliche
///////////////////////////////////////////////////////////

const TString& sl_trova_elaborazione(const TRectype& doc)
{
  const TString& codnum  = doc.get(DOC_CODNUM); // SAL
  TString str;
  str << "USE %ELD SELECT (STR(I0=\"0\"))&&(S3=\"sl0 -1\")&&(S5=\"" << codnum << "\")";
  
  TRecordset* eld = create_recordset(str);
  if (eld != NULL)
  {
    TString16 cod;
    for (bool ok = eld->move_first(); ok; ok = eld->move_next())
    {
      const TString& c = eld->get("CODTAB").as_string();
      const TElaborazione e(c);
      if (e.is_document_ok(doc))
      {
        cod = c;
        break;
      }
    }
    delete eld;
    return get_tmp_string() = cod;
  }
  return EMPTY_STRING;
}

const TString& sl_trova_elaborazione(const TMask& m)
{
  TRectype doc(LF_DOC);
  doc.put(DOC_PROVV,   'D');
  doc.put(DOC_ANNO,    m.get(DOC_ANNO));
  doc.put(DOC_CODNUM,  m.get(DOC_CODNUM));
  doc.put(DOC_NDOC,    m.get(DOC_NDOC));
  doc.put(DOC_TIPODOC, m.get(DOC_TIPODOC));
  doc.put(DOC_STATO,   m.get(DOC_STATO));
  return sl_trova_elaborazione(doc);
}

bool sl_genera_documento(TRectype& doc, const TString& cod)
{
  TString16 codelab = cod;
  if (codelab.blank())
    codelab = sl_trova_elaborazione(doc);

  TCertificazione e(codelab);

  const TDate oggi(TODAY);
  TLista_documenti doc_in, doc_out;
  doc_in.add(new TDocumento(doc));

  bool ok = e.elabora(doc_in, doc_out, oggi, true);
  if (ok)
  {
    int err = doc_in.rewrite();
    if (err == NOERR)
    {
      const TRectype& idoc = doc_in[0];
      for (int i = 0; i < idoc.items(); i++)
      {
        const char* fld = idoc.fieldname(i);
        const TString& val = idoc.get(fld);
        if (val.full())
          doc.put(fld, val);
      }

      err = doc_out.write();
      if (err == NOERR)
        message_box(FR("E' stato generato il certificato %ld"), doc.get_long(DOC_NUMANT));
      else
        error_box(TR("Errore %d in scrittura del certificato"), err);
    }
  }
  
  return ok;
}

///////////////////////////////////////////////////////////
// TCertificazione_app
///////////////////////////////////////////////////////////

class TCertificazione_app : public TSkeleton_application
{
protected:
  virtual void main_loop();
};

void TCertificazione_app::main_loop()
{
  TFilename ininame;
  if (argc() >= 2)
  {
    const TFixed_string arg = argv(2);
    ininame = arg.starts_with("-i", true) ? arg.mid(2) : arg;
  }

  TConfig ini(ininame, "Transaction");
  const TString8 codelab = ini.get("Action");

  ini.set_paragraph("33");
  TRectype doc(LF_DOC);
  doc.put(DOC_PROVV,  ini.get(DOC_PROVV));
  doc.put(DOC_ANNO,   ini.get(DOC_ANNO));
  doc.put(DOC_CODNUM, ini.get(DOC_CODNUM));
  doc.put(DOC_NDOC,   ini.get(DOC_NDOC));

  if (sl_genera_documento(doc, codelab))
  {
    ini.set_paragraph("Transaction");
    ini.set("Result", "OK");
    ini.set("Error", "0");
    
    ini.set_paragraph("33");
    for (int i = 0; i < doc.items(); i++)
    {
      const char* fld = doc.fieldname(i);
      const TString& val = doc.get(fld);
      if (val.full())
        ini.set(fld, val);
    }
  }
}

int sl0200(int argc, char* argv[])
{
  TCertificazione_app a;
  a.run(argc, argv, TR("Certificazione di pagamento"));
  return 0;
}