package FS::ClientAPI::Agent;

#some false laziness w/MyAccount

use strict;
use vars qw($cache);
use subs qw(_cache);
use Digest::MD5 qw(md5_hex);
use FS::Record qw(qsearchs); # qsearch dbdef dbh);
use FS::ClientAPI_SessionCache;
use FS::agent;
use FS::cust_main::Search qw(smart_search);
use FS::svc_domain;
use FS::svc_acct;

sub _cache {
  $cache ||= new FS::ClientAPI_SessionCache( {
               'namespace' => 'FS::ClientAPI::Agent',
             } );
}

sub new_agent {
  my $p = shift;

  my $conf = new FS::Conf;
  return { error=>'Disabled' } unless $conf->exists('selfservice-agent_signup');

  #add a customer record and set agent_custnum?

  my $agent = new FS::agent {
    'typenum'   => $conf->config('selfservice-agent_signup-agent_type'),
    'agent'     => $p->{'agent'},
    'username'  => $p->{'username'},
    '_password' => $p->{'password'},
    #
  };

  my $error = $agent->insert;
  
  return { 'error' => $error } if $error;

  agent_login({ 'username' => $p->{'username'},
                'password' => $p->{'password'},
             });
}

sub agent_login {
  my $p = shift;

  #don't allow a blank login to first unconfigured agent with no user/pass
  return { error => 'Must specify your reseller username and password.' }
    unless length($p->{'username'}) && length($p->{'password'});

  my $agent = qsearchs( 'agent', {
    'username'  => $p->{'username'},
    '_password' => $p->{'password'},
  } );

  unless ( $agent ) { return { error => 'Incorrect password.' } }

  my $session = { 
    'agentnum' => $agent->agentnum,
    'agent'    => $agent->agent,
  };

  my $session_id;
  do {
    $session_id = md5_hex(md5_hex(time(). {}. rand(). $$))
  } until ( ! defined _cache->get($session_id) ); #just in case

  _cache->set( $session_id, $session, '1 hour' );

  { 'error'      => '',
    'session_id' => $session_id,
  };
}

sub agent_logout {
  my $p = shift;
  if ( $p->{'session_id'} ) {
    _cache->remove($p->{'session_id'});
    return { 'error' => '' };
  } else {
    return { 'error' => "Can't resume session" }; #better error message
  }
}

sub agent_info {
  my $p = shift;

  my $session = _cache->get($p->{'session_id'})
    or return { 'error' => "Can't resume session" }; #better error message

  #my %return;

  my $agentnum = $session->{'agentnum'};

  my $agent = qsearchs( 'agent', { 'agentnum' => $agentnum } )
    or return { 'error' => "unknown agentnum $agentnum" };

  { 'error'        => '',
    'agentnum'     => $agentnum,
    'agent'        => $agent->agent,
    'num_prospect' => $agent->num_prospect_cust_main,
    'num_active'   => $agent->num_active_cust_main,
    'num_susp'     => $agent->num_susp_cust_main,
    'num_cancel'   => $agent->num_cancel_cust_main,
    #%return,
  };

}

sub agent_list_customers {
  my $p = shift;

  my $session = _cache->get($p->{'session_id'})
    or return { 'error' => "Can't resume session" }; #better error message

  #my %return;

  my $agentnum = $session->{'agentnum'};

  my $agent = qsearchs( 'agent', { 'agentnum' => $agentnum } )
    or return { 'error' => "unknown agentnum $agentnum" };

  my @cust_main = smart_search( 'search'   => $p->{'search'},
                                'agentnum' => $agentnum,
                              );

  #aggregate searches
  push @cust_main,
    map $agent->$_(), map $_.'_cust_main',
      grep $p->{$_}, qw( prospect active susp cancel );

  #eliminate dups?
  my %saw = ();
  @cust_main = grep { !$saw{$_->custnum}++ } @cust_main;

  { customers => [ map {
                         my $cust_main = $_;
                         my $hashref = $cust_main->hashref;
                         $hashref->{$_} = $cust_main->$_()
                           foreach qw(name status statuscolor status_label);
                         delete $hashref->{$_} foreach qw( payinfo paycvv );
                         $hashref;
                   } @cust_main
                 ],
  }

}

sub check_username {
  my $p = shift;
  my($session, $agentnum, $svc_acct) = _session_agentnum_svc_acct($p);
  return { 'error' => $session } unless ref($session);

  { 'error'     => '',
    #'username'  => $username,
    #'domain'    => $domain,
    'available' => $svc_acct ? 0 : 1,
  };

}

sub _session_agentnum_svc_acct {
  my $p = shift;

  my $session = _cache->get($p->{'session_id'})
    or return "Can't resume session"; #better error message

  my $username = $p->{'username'};

  #XXX some way to default this per agent (by default product's service def?)
  my $domain = $p->{'domain'};

  my $svc_domain = qsearchs('svc_domain', { 'domain' => $domain } )
    or return { 'error' => 'Unknown domain' };

  my $svc_acct = qsearchs('svc_acct', { 'username' => $username,
                                        'domsvc'   => $svc_domain->svcnum, } );

  ( $session, $session->{'agentnum'}, $svc_acct );

}

sub _session_agentnum_cust_pkg {
  my $p = shift;
  my($session, $agentnum, $svc_acct) = _session_agentnum_svc_acct($p);
  return $session unless ref($session);
  return 'Account not found' unless $svc_acct;
  my $cust_svc = $svc_acct->cust_svc;
  return 'Unlinked account' unless $cust_svc->pkgnum;
  my $cust_pkg = $cust_svc->cust_pkg;
  return 'Not your account' unless $cust_pkg->cust_main->agentnum == $agentnum;
  ($session, $agentnum, $cust_pkg);
}

sub suspend_username {
  my $p = shift;
  my($session, $agentnum, $cust_pkg) = _session_agentnum_cust_pkg($p);
  return { 'error' => $session } unless ref($session);

  return { 'error' => $cust_pkg->suspend };
}

sub unsuspend_username {
  my $p = shift;
  my($session, $agentnum, $cust_pkg) = _session_agentnum_cust_pkg($p);
  return { 'error' => $session } unless ref($session);

  return { 'error' => $cust_pkg->unsuspend };
}

1;
