#!/usr/bin/perl

use 5.038.2;

for ( qw(which echo) ){
    my $good = `which $_`;
    if (length($good) < 3){
	say "$_ not present. Aborting yet.\n";
	exit -10;
    }
}

my $file = "crm.csv";
my $memo = "crm.memo";
my $appointments = "crm.appointments";

unless (@ARGV){
    say "\nUsage: $0 <data|list>";
    say "";
    say "Data - input, dump or modify database";
    say "Calls - review the data to make calls";
    say "(Other parameters reject uptodate)\n";
    say "Customer Relationship Management idea\n";
    exit -1;
}

unless (-e $file){
    system "echo > $file";
}
unless (-e $memo){
    system "echo > $memo";
}
unless (-e $appointments){
    system "echo > $appointments";
}

# muestreo rotatorio con intervalos mínimos (no posible sin hacerlo demonio) y máximos

my $args = join " ", @ARGV;
my ($n,$p,$ph);   # name, PID, phone(s)

die "Error: parameters are data or list" unless ($args =~ /data/i || $args =~ /calls/i);

if ($args =~ /data/i){
    
    my $resp = 10_000;       # ??? variable para aceptar input stdin de lo que sea
                             # aumentado v.0.003c para que no sea límite
    while ($resp > 0) {

	$resp = menu();     # Esta línea presenta un menu principal de la opción "data" 
	
	if ($resp == 1){
	    say "\n\nCREATION PROCEDURE\n";
	    say "Whithout commas,\n";
	    print "\nFull name: ";
	    chomp (my $n = <STDIN>);
	    $n =~ s/\,//g;
	    print "\nPID: ";
	    chomp (my $p = <STDIN>);
	    $p =~ s/\,//g;
	    print "\nPhone(s): ";
	    chomp (my $ph = <STDIN>);
	    $ph =~ s/\,/-/g;
	    open my $OUT, '>>', $file or die $!;
	    say $OUT "$n,$p,$ph,". infofecha() .",";
	    close $OUT;
	    print "-+- \a";              # ahora puede haber muchas terminales sin campana
	}elsif ($resp == 2){
	    say "\n\nDELETE PROCEDURE\n";
	    print "Say yes to continue: ";
	    chomp (my $confir = <STDIN>);
	    if ($confir =~ /yes/i){
		($n, $p, $ph) = ask(1);
		open my $IN, '<', $file or die $!;
		my @g = <$IN>;
		close $IN;
		open my $OUT2, '>', $file or die $!;   
		for (@g) {
		    unless (/$n/i && /$p/i && /$ph/i){
			say $OUT2 $_;
		    }
		}
		close $OUT2;
	    }
	    print "-+- \a";
	}elsif ($resp == 3){
	    say "\n\nMODIFY PROCCESS:\n";
	    ($n, $p, $ph) = ask(1);
		
	    open my $IN2 , '<', $file or die $!;
	    my @g = <$IN2>;
	    close $IN2;
	    open my $OUT3, '>', $file or die $!;
	    if (/$n/i || /$p/i || /$ph/i){		  
		print $OUT3 "$n,$p,$ph," ;
		while ( /\,(\d{8})/ ){
		    print $OUT3 $1 . ",";
		}
		say $OUT3 infofecha().",";
		say $OUT3 "";
	    }else{
		say $OUT3 $_;
	    }
	    close $OUT3;
	    print "-+- \a";
	}elsif ($resp == 4){
	    say "\n\nDATA DUMP BEGIN HERE";
	    say "====================";
	    open my $IN3, '<', $file or die $!;
	    print $_ for (<$IN3>);
	    close $IN3;
	    say "==================";
	    say "DATA DUMP END HERE";
	    say "==================\n";
	}elsif ($resp == 5){
	    say "\n\nMEMOS DUMP BEGIN HERE";
	    say "=====================";
	    open my $IN3, '<', $memo or die $!;
	    print $_ for <$IN3>;
	    close $IN3;
	    say "===================";
	    say "MEMOS DUMP END HERE";
	    say "===================\n";
	}elsif ($resp == 6) {		
	    say "\n\nAPPOIMENTS DUMP BEGIN HERE";
	    say "==========================";
	    open my $IN4, '<', $appointments or die $!;
	    print $_ for <$IN4>;
	    close $IN4;
	    say "========================";
	    say "APPOIMENTS DUMP END HERE";
	    say "========================\n";
	}elsif ($resp == 7){
	    ask(2);
	}else{
#	    last;             # exit of the program
	    # es evidente que aquí elsif($resp == 999) { goto donmarciano; }
	    $resp = 0;        # soft exit
	}
	if ($resp >= 4 && $resp <=7){
	    my $pause = <STDIN>;
	    print "-+- \a";
	}
    }

}elsif ($args =~ /calls/i){                 # Aquí está lo principal del programa, el objetivo "list"

    print "\n\nMax time passed since last call: ";
    chomp (my $max = <STDIN>);
    if ($max eq "" || 0+$max ne $max || $max <0) { $max = 0; }
    say "\nList of entries with dates lower than max time reached";
    say "------------------------------------------------------\n";
    my $nowuseful = infofecha() - $max;
    
    open my $IN5, '<', $file or die $!;
    my @global = <$IN5>;
    close $IN5;
        
    for (@global){
	chomp;
	/\,(\d{8})\,/;                  # detecta una fecha iso
	if (defined $1){
	    if ($1 <= $nowuseful){
		say $_;
	    }
	}
    }

    say "=== Phone calls to be done/undone ===";
    open my $AP, "+<", $appointments or die $!;
    seek ($AP, 0, 1);
    my @aps = <$AP>;
    my $tmp;
    for my $l (@global){
	### delicado, es modificación porque hay que añadir infofecha a las lineas
	chomp $l;
	say $l;    # client data
	for my $aa (@aps){
	    $aa =~ /(.+)\,/;
	    if (defined $1){
		$tmp = $1;
		if ( $l =~ /$tmp/i ){
		    print "Appointement => $tmp,";
		    while ($aa =~ /\,(\d{8})/g){
			if (defined $1){
			    print "$1,";     # past or future appointment
			}
		    }
		    say "";
		}
	    }
	}
	$l =~ /\,(\d{8})\,$/;
	if (defined $1){
	    if ($1 <= $nowuseful){
		print "\t===> Call? [y/N]: ";
		chomp (my $yn = <STDIN>);
		my $ref;
		$l =~ /(.+)\,\d{8}\,/;
		if (defined $1){
		    $ref = $1;
		    if ($yn =~ /[Y|y|S|s]/){
			my $line = $l . infofecha() . ",";
			open my $OUT4, '>>', $file or die $!;
			say $OUT4 $line;
			close $OUT4;
			open my $MEMO, '>>', $memo or die $!;
			my $last = tell( $MEMO );                     # recordatorio de posición antes de modificación. Al ser abierto append, de lo último
			seek ($MEMO, 0, 1);
			my $ok;
			while (<$MEMO>){
			    chomp;
			    if (/\,\d{8}\,/ && /$ref/i){ $ok++; }
			    say ':: ', $_ if $ok;
			    if ( /\,\d{8}\,/ && $_ !~ /$ref/i ){
				$ok =0;
			    }
			}
			seek ($MEMO, $last, 0);
			say $MEMO $line if ($line);
			my $note = "MEMO field>";                          # por si se deja en blanco
			while ($note !~ /^\s+$/){		    
			    print "MEMO (end with blank line)>";
			    chomp ($note = <STDIN>);
			    say $MEMO $note if ($note);
			}
			say $MEMO "Closed at ", scalar(localtime());
			close $MEMO;
		    }else{
again:		    
			  print "Insert ISO date (i.e. 19991231 - 8 digits - or nothing to escape) to make a new appointment: ";
			chomp (my $dateap = <STDIN>);
			if (defined $dateap){
			    if ($dateap =~ /^\d{8}$/){ 
				say $AP $ref . "," . $dateap;
				say "New appoiment => $dateap";
			    }elsif ($dateap eq ""){
				# escape
			    }elsif ( checkfecha($dateap) == 0 ){
				goto again;
			    }
			} 
		    }
		}
	    }
	}
    }
    close $AP;
}

say "\nGood bye!";

exit 3;




sub menu {
    my $r;
top:    
    system "clear";
    say "\nCRM ($0) DATA MENU:\n";
    say "1) Altas [default]\n";
    say "2) Bajas\n";
    say "3) Modificaciones\n";
    say "4) Dump data\n";
    say "5) Dump memos\n";
    say "6) Dump appointments\n";
    say "7) Consultas\n";
    say "0) Salir\n\n";
    print "?> ";
    chomp ($r = <STDIN>);
    if ($r =~ /[1|A|a|\n]/){
	return 1;
    }elsif ($r =~ /[2|B|b]/){
	return 2;
    }elsif ($r =~ /[3|M|m]/){
	return 3;
    }elsif ($r =~ /[4|D|d]/){
	return 4;
    }elsif ($r =~ /[5|O|o]/){
	return 5;
    }elsif ($r =~ /[6|P|p]/){
	return 6;
    }elsif ($r =~ /[7|C|c]/){
	return 7;
    }elsif ($r =~ /[0|S|s|\-]/){
	return 0;
    }else{
#	goto top;
    }
}

sub ask {
    my $opt = shift;
    system "clear";
    print "\nName: ";
    chomp (my $n = <STDIN>);
    print "\nPID: ";
    chomp (my $p = <STDIN>);
    print "\nPhone(s): ";
    chomp (my $ph = <STDIN>);
    open my $IN6, '<', $file or die $!;
    my @g = <$IN6>;
    close $IN6;
    say "\nSelected record(s):";
    say "-------------------\n";
    my $c =0;
    for (@g){
	chomp;
	if (/$n/i && /$p/i && /$ph/i){
	    say $_;
	    $c++;
	}
	if ($opt == 2 && (/$n/ || /$p/ || /$ph/) ){
	    say $_;
	    $c++;
	}
    }
    say "Count $c record(s)";
    say "Select better to modify or delete." if $c > 1;
    
    return ($n, $p, $ph);
}

sub checkfecha {
    my $f = shift;
    return 0 if (length($f) != 8);
    return 0 unless ($f =~ / (2\d{3}) (\d\d) (\d\d) /x);
    my $y = $1;
    my $m = $2;
    my $d = $3;
    if (defined $m){
	# es un mes, y no se admite base 0. Hay formatos que sí
	return 0 if $m <= 0;
	return 0 if $m > 12;
    }
    if (defined $d){
	return 0 if $d <= 0;
	return 0 if $d > daysinmonth( $m, $y );
    }
    return 1;    # ok
}
    
sub normaltoISO {
    my $f = shift;
    my $d = substr $f, 0, 2, "";
    my $m = substr $f, 0, 2, "";
    my $ISO = $f . $m . $d;
    return $ISO;
}

sub ISOtonormal {
    my $f = shift;
    my $y = substr $f, 0, 4, "";
    my $m = substr $f, 0, 2, "";
    my $normal = $f . $m . $y;
    return $normal;
}
    
sub infofecha {
#    my $i = shift;
    my $i = scalar localtime();
    my @datetime = split " ", $i;
                  
    my $anyo = $datetime[4];
    #    if ($anyo<66) { $anyo += 2000; }
    #    elsif ($anyo<100) { $anyo += 1900; }
    my %mes = (
        Jan => "01",
        Feb => "02",
        Mar => "03",
        Apr => "04",
        May => "05",
        Jun => "06",
        Jul => "07",
        Aug => "08",
        Sep => "09",
        Oct => "10",
        Nov => "11",
        Dec => "12",
    );
                                                          
    my $nmes = $mes{ $datetime[1] };
    my $j = $datetime[2];
    my $dia = sprintf "%02d", $j;
    return $anyo  . $nmes   . $dia;
}

### subrutinas del calendario gregoriano, para meter en checkfecha(). El problema es la gestión del error

sub febrero {
    my $y = shift;
    if ($y % 400 == 0){   return 29;
    }elsif ( $y % 100 == 0){  return 28;
    }elsif ($y % 4 == 0){  return 29;
    }else{      return 28;  }
}

sub daysinmonth {
    my ($m, $y) = @_;
    if ($m==1 || $m==3 || $m==5 || $m==7 || $m==8 || $m==10 || $m==12){ return 31; }
    if ($m==4 || $m==6 || $m==9 || $m==11){ return 30; }
    if ($m==2){ return (febrero($y)); }
    if ($m==0){ return 0; }
    else{ return -1; }
}


__END__
  
v.0.001 UNTESTED
v.0.002 UNTESTED Added memo fields for calls
v.0.003 UNTESTED Added appointments
v.0.003b UNTESTED memo fields improved
v.0.004c sigue sin testear, hay una cifra mágica 100 días, cuidar lo de múltiples teléfonos  
         -> se mete checkfecha() y se elige error temprano 
